Skip to content

[beta] backports #140269

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool
return true;
}

// Both the old and the new ABIs treat vector types like `v128` the same
// way.
if uses_vector_registers(&arg.mode, &arg.layout.backend_repr) {
return true;
}

// This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
if arg.layout.is_aggregate() {
let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
Expand All @@ -111,6 +117,11 @@ fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool
}
}

// Zero-sized types are dropped in both ABIs, so they're safe
if arg.layout.is_zst() {
return true;
}

false
}

Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2066,6 +2066,17 @@ impl<'a> Parser<'a> {
}
self.expect_field_ty_separator()?;
let ty = self.parse_ty()?;
if self.token == token::Colon && self.look_ahead(1, |t| *t != token::Colon) {
self.dcx()
.struct_span_err(self.token.span, "found single colon in a struct field type path")
.with_span_suggestion_verbose(
self.token.span,
"write a path separator here",
"::",
Applicability::MaybeIncorrect,
)
.emit();
}
let default = if self.token == token::Eq {
self.bump();
let const_expr = self.parse_expr_anon_const()?;
Expand Down
20 changes: 7 additions & 13 deletions compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,19 +248,13 @@ impl<'a> Parser<'a> {
segments.push(segment);

if self.is_import_coupler() || !self.eat_path_sep() {
let ok_for_recovery = self.may_recover()
&& match style {
PathStyle::Expr => true,
PathStyle::Type if let Some((ident, _)) = self.prev_token.ident() => {
self.token == token::Colon
&& ident.as_str().chars().all(|c| c.is_lowercase())
&& self.token.span.lo() == self.prev_token.span.hi()
&& self
.look_ahead(1, |token| self.token.span.hi() == token.span.lo())
}
_ => false,
};
if ok_for_recovery
// IMPORTANT: We can *only ever* treat single colons as typo'ed double colons in
// expression contexts (!) since only there paths cannot possibly be followed by
// a colon and still form a syntactically valid construct. In pattern contexts,
// a path may be followed by a type annotation. E.g., `let pat:ty`. In type
// contexts, a path may be followed by a list of bounds. E.g., `where ty:bound`.
if self.may_recover()
&& style == PathStyle::Expr // (!)
&& self.token == token::Colon
&& self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
{
Expand Down
35 changes: 22 additions & 13 deletions compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,27 +583,36 @@ fn receiver_is_dispatchable<'tcx>(
// create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
// its supertraits) added to caller bounds. `U: ?Sized` is already implied here.
let param_env = {
let param_env = tcx.param_env(method.def_id);
// N.B. We generally want to emulate the construction of the `unnormalized_param_env`
// in the param-env query here. The fact that we don't just start with the clauses
// in the param-env of the method is because those are already normalized, and mixing
// normalized and unnormalized copies of predicates in `normalize_param_env_or_error`
// will cause ambiguity that the user can't really avoid.
//
// We leave out certain complexities of the param-env query here. Specifically, we:
// 1. Do not add `~const` bounds since there are no `dyn const Trait`s.
// 2. Do not add RPITIT self projection bounds for defaulted methods, since we
// are not constructing a param-env for "inside" of the body of the defaulted
// method, so we don't really care about projecting to a specific RPIT type,
// and because RPITITs are not dyn compatible (yet).
let mut predicates = tcx.predicates_of(method.def_id).instantiate_identity(tcx).predicates;

// Self: Unsize<U>
let unsize_predicate =
ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]).upcast(tcx);
ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]);
predicates.push(unsize_predicate.upcast(tcx));

// U: Trait<Arg1, ..., ArgN>
let trait_predicate = {
let trait_def_id = method.trait_container(tcx).unwrap();
let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
});

ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx)
};
let trait_def_id = method.trait_container(tcx).unwrap();
let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
});
let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
predicates.push(trait_predicate.upcast(tcx));

normalize_param_env_or_error(
tcx,
ty::ParamEnv::new(tcx.mk_clauses_from_iter(
param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]),
)),
ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
)
};
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/associated-consts/issue-93835.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
fn e() {
type_ascribe!(p, a<p:p<e=6>>);
//~^ ERROR cannot find type `a` in this scope
//~| ERROR path separator must be a double colon
//~| ERROR cannot find value
//~| ERROR associated const equality
//~| ERROR cannot find trait `p` in this scope
//~| ERROR associated const equality
//~| ERROR failed to resolve: use of unresolved module or unlinked crate `p`
}

fn main() {}
32 changes: 9 additions & 23 deletions tests/ui/associated-consts/issue-93835.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
error: path separator must be a double colon
--> $DIR/issue-93835.rs:4:25
|
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^
|
= note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | type_ascribe!(p, a<p::p<e=6>>);
| +

error[E0425]: cannot find value `p` in this scope
--> $DIR/issue-93835.rs:4:19
|
Expand All @@ -22,6 +10,12 @@ error[E0412]: cannot find type `a` in this scope
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^ not found in this scope

error[E0405]: cannot find trait `p` in this scope
--> $DIR/issue-93835.rs:4:26
|
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^ not found in this scope

error[E0658]: associated const equality is incomplete
--> $DIR/issue-93835.rs:4:28
|
Expand All @@ -43,15 +37,7 @@ LL | type_ascribe!(p, a<p:p<e=6>>);
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0433]: failed to resolve: use of unresolved module or unlinked crate `p`
--> $DIR/issue-93835.rs:4:24
|
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^ use of unresolved module or unlinked crate `p`
|
= help: you might be missing a crate named `p`

error: aborting due to 6 previous errors
error: aborting due to 5 previous errors

Some errors have detailed explanations: E0412, E0425, E0433, E0658.
For more information about an error, try `rustc --explain E0412`.
Some errors have detailed explanations: E0405, E0412, E0425, E0658.
For more information about an error, try `rustc --explain E0405`.
26 changes: 13 additions & 13 deletions tests/ui/associated-types/issue-59324.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,18 @@ LL | |
LL | | &self,
LL | | ) -> Self::AssocType;
| |_________________________^ the trait `Foo` is not implemented for `Bug`

error[E0277]: the trait bound `(): Foo` is not satisfied
--> $DIR/issue-59324.rs:24:29
|
help: consider further restricting type parameter `Bug` with trait `Foo`
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
|
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
| +++++
help: this trait has no implementations, consider adding one
--> $DIR/issue-59324.rs:3:1
|
LL | pub trait Foo: NotFoo {
| ^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `Bug: Foo` is not satisfied
--> $DIR/issue-59324.rs:16:5
Expand All @@ -51,18 +58,11 @@ LL | |
LL | | &self,
LL | | ) -> Self::AssocType;
| |_________________________^ the trait `Foo` is not implemented for `Bug`

error[E0277]: the trait bound `(): Foo` is not satisfied
--> $DIR/issue-59324.rs:24:29
|
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
|
help: this trait has no implementations, consider adding one
--> $DIR/issue-59324.rs:3:1
help: consider further restricting type parameter `Bug` with trait `Foo`
|
LL | pub trait Foo: NotFoo {
| ^^^^^^^^^^^^^^^^^^^^^
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
| +++++

error[E0277]: the trait bound `Bug: Foo` is not satisfied
--> $DIR/issue-59324.rs:20:10
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
error: path separator must be a double colon
--> $DIR/single-colon-path-not-const-generics.rs:8:18
|
LL | pub struct Foo {
| --- while parsing this struct
LL | a: Vec<foo::bar:A>,
| ^
|
= note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | a: Vec<foo::bar::A>,
| +
| +

error: aborting due to 1 previous error

18 changes: 17 additions & 1 deletion tests/ui/lint/wasm_c_abi_transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//@ add-core-stubs
//@ build-fail

#![feature(no_core)]
#![feature(no_core, repr_simd)]
#![no_core]
#![crate_type = "lib"]
#![deny(wasm_c_abi)]
Expand Down Expand Up @@ -39,3 +39,19 @@ pub fn call_other_fun(x: MyType) {
unsafe { other_fun(x) } //~ERROR: wasm ABI transition
//~^WARN: previously accepted
}

// Zero-sized types are safe in both ABIs
#[repr(C)]
pub struct MyZstType;
#[allow(improper_ctypes_definitions)]
pub extern "C" fn zst_safe(_x: (), _y: MyZstType) {}

// The old and new wasm ABI treats simd types like `v128` the same way, so no
// wasm_c_abi warning should be emitted.
#[repr(simd)]
#[allow(non_camel_case_types)]
pub struct v128([i32; 4]);
#[target_feature(enable = "simd128")]
pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
//~^ WARN `extern` fn uses type `v128`, which is not FFI-safe
//~| WARN `extern` fn uses type `v128`, which is not FFI-safe
31 changes: 30 additions & 1 deletion tests/ui/lint/wasm_c_abi_transition.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
warning: `extern` fn uses type `v128`, which is not FFI-safe
--> $DIR/wasm_c_abi_transition.rs:55:35
|
LL | pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
| ^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
--> $DIR/wasm_c_abi_transition.rs:53:1
|
LL | pub struct v128([i32; 4]);
| ^^^^^^^^^^^^^^^
= note: `#[warn(improper_ctypes_definitions)]` on by default

warning: `extern` fn uses type `v128`, which is not FFI-safe
--> $DIR/wasm_c_abi_transition.rs:55:44
|
LL | pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
| ^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
--> $DIR/wasm_c_abi_transition.rs:53:1
|
LL | pub struct v128([i32; 4]);
| ^^^^^^^^^^^^^^^

error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
--> $DIR/wasm_c_abi_transition.rs:18:1
|
Expand Down Expand Up @@ -33,7 +62,7 @@ LL | unsafe { other_fun(x) }
= note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target

error: aborting due to 3 previous errors
error: aborting due to 3 previous errors; 2 warnings emitted

Future incompatibility report: Future breakage diagnostic:
error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
Expand Down
22 changes: 22 additions & 0 deletions tests/ui/parser/ty-path-followed-by-single-colon.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Paths in type contexts may be followed by single colons.
// This means we can't generally assume that the user typo'ed a double colon.
// issue: <https://github.com/rust-lang/rust/issues/140227>
//@ check-pass
#![crate_type = "lib"]
#![expect(non_camel_case_types)]

#[rustfmt::skip]
mod garden {

fn f<path>() where path:to::somewhere {} // OK!

fn g(_: impl Take<path:to::somewhere>) {} // OK!

#[cfg(any())] fn h() where a::path:to::nowhere {} // OK!

fn i(_: impl Take<path::<>:to::somewhere>) {} // OK!

mod to { pub(super) trait somewhere {} }
trait Take { type path; }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//@ check-pass

// Regression test for <https://github.com/rust-lang/rust/issues/138937>.

// Previously, we'd take the normalized param env's clauses which included
// `<PF as TraitC>::Value = i32`, which comes from the supertraits of `TraitD`
// after normalizing `<PF as TraitC>::Value = <PF as TraitD>::Scalar`. Since
// `normalize_param_env_or_error` ends up re-elaborating `PF: TraitD`, we'd
// end up with both versions of this predicate (normalized and unnormalized).
// Since these projections preds are not equal, we'd fail with ambiguity.

trait TraitB<T> {}

trait TraitC: TraitB<Self::Value> {
type Value;
}

trait TraitD: TraitC<Value = Self::Scalar> {
type Scalar;
}

trait TraitE {
fn apply<PF: TraitD<Scalar = i32>>(&self);
}

fn main() {}

This file was deleted.

15 changes: 0 additions & 15 deletions tests/ui/suggestions/argument-list-from-path-sep-error-129273.rs

This file was deleted.

Loading
Loading