Skip to content

Call trait methods from class impls#364

Merged
tjpalmer merged 8 commits intomainfrom
rust-202602b
Mar 2, 2026
Merged

Call trait methods from class impls#364
tjpalmer merged 8 commits intomainfrom
rust-202602b

Conversation

@tjpalmer
Copy link
Contributor

@tjpalmer tjpalmer commented Feb 27, 2026

  • This is one of the focus issues right now, but others remain to be fixed
  • Also ignore warnings before ignoring unit never type fallback

Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
),
)
internal fun allowWarnings(pos: Position) = run {
// Separate them with `warnings` first, to prevent warnings against the other on older rust.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least, I seemed to see effects per the comment above, but I didn't spend a lot of time on this aspect.

private var insideMutableType = false
private val failVars = mutableSetOf<ResolvedName>()
private val functionContextStack = mutableListOf<FunctionContext>()
private val logSink = LogSink.devNull // TODO what?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need some log sink, and this works for now, but maybe should reconsider or even just pass log sinks into translators. I've wanted that more than once before.

// Build the builder.
// Here we make `WhateverBuilder` for requireds and/or `WhateverBuilderOptions` structs for optionals.
// Build the maker.
// Here we make `WhateverMaker` for requireds and/or `WhateverMakerOptions` structs for optionals.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Builder is more idiomatic, but I think people will cope.

): List<Rust.Item> = run {
// We're here because this class has no matching member, so walk its supertypes to match the super method.
// The method we inherit closest might be on a different branch.
val overrides = findOverrides(decl.typeShape, superShape, typeContext, logSink)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I factored out findOverrides from existing logic. I think it meets the needs here.

addAll(argIds)
},
)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now factored to share logic with trait-wrapper-to-trait forwarding that I put in on the previous pr. The main difference is what happens inside the forwarding method, so that's what the callback is for.

| }
| fn whatever(& self) -> std::sync::Arc<String> {
| BTrait::whatever(self)
| }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explicitly call B's whatever, since that's the resolution found.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explicitly call B's whatever, since that's the resolution found.

Actually, that just results in infinite recursion when the impl is for B, because it just comes back here. Instead just allow the BTrait default implementation to be called implicitly.

| fn set_prop(& self, value: std::sync::Arc<String>) {
| ATrait::set_prop( & ( * self.0), value)
| }
|}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This trait wrapper to trait stuff isn't new, but interface D is new in the test case, so it's extra lines in the codegen here.

| }
| fn set_prop(& self, value: std::sync::Arc<String>) {
| DTrait::set_prop(self, value)
| }
Copy link
Contributor Author

@tjpalmer tjpalmer Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call A for greeting implicitly, B for whatever, and own F impl for thing. Others are picked up by D.

This looks correct to me by eyeball check vs the temper code above, but I haven't tested the new code to compile and run with rust yet.


@Test
fun needlesslyGenericBuilder() {
fun needlesslyGenericMaker() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case still is for testing #271, and I still haven't fixed that issue.


member.overriddenMembers = overriddenMembers.toSet()
return overriddenMembers.toSet()
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Factored out a new public function for use in be-rust. I can't just use overriddenMembers (as also discussed in comments), because I need to know the overrides for methods that don't exist directly in the base type.

Signed-off-by: Tom <tom@temper.systems>
@tjpalmer tjpalmer marked this pull request as ready for review February 27, 2026 23:39
}
// TODO Ensure unique names.
val builderId = "${targetId.outName.outputNameText}Builder".toId(targetId.pos)
val builderId = "${targetId.outName.outputNameText}Maker".toId(targetId.pos)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you prefer Maker to Builder?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you prefer Maker to Builder?

I prefer Builder because it's more idiomatic. I was just trying to be friendlier with Temper conventions.

That said, I have a new idea. I was trying to make one branch for all the outstanding issues again, but since I've gotten the pivot, I can't finish it immediately, anyway. I'll back out the Builder changes from this pr, so I can reassess later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've backed out the Builder renaming and written issue #367 about a different strategy to be both idiomatic and more often avoid naming conflicts.

Signed-off-by: Tom <tom@temper.systems>
fn.parameters.restParameter != null && return
// Build the builder.
// Here we make `WhateverBuilder` for requireds and/or `WhateverBuilderOptions` structs for optionals.
// Here we make `WhateverBuilder` for requireds and/or `WhateverOptions` structs for optionals.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed in passing that this comment was wrong vs current behavior.

@tjpalmer tjpalmer merged commit d421af1 into main Mar 2, 2026
2 checks passed
@tjpalmer tjpalmer deleted the rust-202602b branch March 2, 2026 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants