From 7fe0cd6d3b1f7bdbdcf25d8a5d90582f577d63d4 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 12 Jan 2024 16:07:20 +0100 Subject: [PATCH 1/6] rename `reported_signature_mismatch` to reflect its use --- compiler/rustc_infer/src/infer/at.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 4 ++-- .../src/traits/error_reporting/type_err_ctxt_ext.rs | 4 +--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 09313cd9738c2..e60e3ffeaa72c 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -84,7 +84,7 @@ impl<'tcx> InferCtxt<'tcx> { selection_cache: self.selection_cache.clone(), evaluation_cache: self.evaluation_cache.clone(), reported_trait_errors: self.reported_trait_errors.clone(), - reported_closure_mismatch: self.reported_closure_mismatch.clone(), + reported_signature_mismatch: self.reported_signature_mismatch.clone(), tainted_by_errors: self.tainted_by_errors.clone(), err_count_on_creation: self.err_count_on_creation, universe: self.universe.clone(), diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index fcc94687ed293..e164041c5991e 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -278,7 +278,7 @@ pub struct InferCtxt<'tcx> { /// avoid reporting the same error twice. pub reported_trait_errors: RefCell>>>, - pub reported_closure_mismatch: RefCell)>>, + pub reported_signature_mismatch: RefCell)>>, /// When an error occurs, we want to avoid reporting "derived" /// errors that are due to this original failure. Normally, we @@ -702,7 +702,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { selection_cache: Default::default(), evaluation_cache: Default::default(), reported_trait_errors: Default::default(), - reported_closure_mismatch: Default::default(), + reported_signature_mismatch: Default::default(), tainted_by_errors: Cell::new(None), err_count_on_creation: tcx.dcx().err_count(), universe: Cell::new(ty::UniverseIndex::ROOT), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 47a700805fa5c..a9fd538b6c0fc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -3459,14 +3459,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did)); let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did)); - if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) { + if !self.reported_signature_mismatch.borrow_mut().insert((span, found_span)) { // We check closures twice, with obligations flowing in different directions, // but we want to complain about them only once. return None; } - self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); - let mut not_tupled = false; let found = match found_trait_ref.skip_binder().args.type_at(1).kind() { From f28373978ee1f4d6c8c9e43a48a693d69ec63547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 12 Jan 2024 16:37:25 +0100 Subject: [PATCH 2/6] Allow `~const` on assoc ty bounds again --- compiler/rustc_ast_passes/messages.ftl | 3 ++ .../rustc_ast_passes/src/ast_validation.rs | 38 ++++++++++++++++--- compiler/rustc_ast_passes/src/errors.rs | 17 +++++++++ ...-type-const-bound-usage-0.qualified.stderr | 14 +++++++ .../assoc-type-const-bound-usage-0.rs | 24 ++++++++++++ ...-type-const-bound-usage-1.qualified.stderr | 14 +++++++ .../assoc-type-const-bound-usage-1.rs | 27 +++++++++++++ .../assoc-type-const-bound-usage.rs | 15 -------- .../assoc-type-const-bound-usage.stderr | 22 ----------- .../rfc-2632-const-trait-impl/assoc-type.rs | 28 ++++++++++---- .../assoc-type.stderr | 22 +++++------ .../tilde-const-invalid-places.stderr | 24 ++++++++++-- .../tilde-const-trait-assoc-tys.rs | 18 +++++++++ 13 files changed, 202 insertions(+), 64 deletions(-) create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.qualified.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs delete mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs delete mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index a10797626f1b2..6586ca5d36f88 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -232,6 +232,9 @@ ast_passes_tilde_const_disallowed = `~const` is not allowed here .trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds .trait_impl = this impl is not `const`, so it cannot have `~const` trait bounds .impl = inherent impls cannot have `~const` trait bounds + .trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds + .trait_impl_assoc_ty = associated types in non-const impls cannot have `~const` trait bounds + .inherent_assoc_ty = inherent associated types cannot have `~const` trait bounds .object = trait objects cannot have `~const` trait bounds .item = this item cannot have `~const` trait bounds diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 7f78f6870552f..9ea5d1ed5fa27 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -37,12 +37,17 @@ enum SelfSemantic { } /// What is the context that prevents using `~const`? +// FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're +// almost identical. This gets rid of an abstraction layer which might be considered bad. enum DisallowTildeConstContext<'a> { TraitObject, Fn(FnKind<'a>), Trait(Span), TraitImpl(Span), Impl(Span), + TraitAssocTy(Span), + TraitImplAssocTy(Span), + InherentAssocTy(Span), Item, } @@ -316,6 +321,7 @@ impl<'a> AstValidator<'a> { constness: Const::No, polarity: ImplPolarity::Positive, trait_ref, + .. } = parent { Some(trait_ref.path.span.shrink_to_lo()) @@ -1286,6 +1292,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // suggestion for moving such bounds to the assoc const fns if available. errors::TildeConstReason::Impl { span } } + &DisallowTildeConstContext::TraitAssocTy(span) => { + errors::TildeConstReason::TraitAssocTy { span } + } + &DisallowTildeConstContext::TraitImplAssocTy(span) => { + errors::TildeConstReason::TraitImplAssocTy { span } + } + &DisallowTildeConstContext::InherentAssocTy(span) => { + errors::TildeConstReason::InherentAssocTy { span } + } DisallowTildeConstContext::TraitObject => { errors::TildeConstReason::TraitObject } @@ -1483,13 +1498,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_item_named(item.ident, "const"); } + let parent_is_const = + self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrTraitImpl::constness).is_some(); + match &item.kind { AssocItemKind::Fn(box Fn { sig, generics, body, .. }) - if self - .outer_trait_or_trait_impl - .as_ref() - .and_then(TraitOrTraitImpl::constness) - .is_some() + if parent_is_const || ctxt == AssocCtxt::Trait || matches!(sig.header.constness, Const::Yes(_)) => { @@ -1505,6 +1519,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ); self.visit_fn(kind, item.span, item.id); } + AssocItemKind::Type(_) => { + let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl { + Some(TraitOrTraitImpl::Trait { .. }) => { + DisallowTildeConstContext::TraitAssocTy(item.span) + } + Some(TraitOrTraitImpl::TraitImpl { .. }) => { + DisallowTildeConstContext::TraitImplAssocTy(item.span) + } + None => DisallowTildeConstContext::InherentAssocTy(item.span), + }); + self.with_tilde_const(disallowed, |this| { + this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)) + }) + } _ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)), } } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index fcf19ce52ec62..e2b8e64b115e5 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -565,6 +565,8 @@ pub struct ConstBoundTraitObject { pub span: Span, } +// FIXME(effects): Consider making the note/reason the message of the diagnostic. +// FIXME(effects): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here). #[derive(Diagnostic)] #[diag(ast_passes_tilde_const_disallowed)] pub struct TildeConstDisallowed { @@ -598,6 +600,21 @@ pub enum TildeConstReason { #[primary_span] span: Span, }, + #[note(ast_passes_trait_assoc_ty)] + TraitAssocTy { + #[primary_span] + span: Span, + }, + #[note(ast_passes_trait_impl_assoc_ty)] + TraitImplAssocTy { + #[primary_span] + span: Span, + }, + #[note(ast_passes_inherent_assoc_ty)] + InherentAssocTy { + #[primary_span] + span: Span, + }, #[note(ast_passes_object)] TraitObject, #[note(ast_passes_item)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr new file mode 100644 index 0000000000000..62c8a442ab9bd --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/assoc-type-const-bound-usage-0.rs:21:6 + | +LL | ::Assoc::func() + | ^ the trait `Trait` is not implemented for `T` + | +help: consider further restricting this bound + | +LL | const fn qualified() -> i32 { + | +++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs new file mode 100644 index 0000000000000..d8573d3af014c --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs @@ -0,0 +1,24 @@ +// FIXME(effects): Collapse the revisions into one once we support `::Proj`. +// revisions: unqualified qualified +//[unqualified] check-pass +//[qualified] known-bug: unknown + +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Trait { + type Assoc: ~const Trait; + fn func() -> i32; +} + +#[cfg(unqualified)] +const fn unqualified() -> i32 { + T::Assoc::func() +} + +#[cfg(qualified)] +const fn qualified() -> i32 { + ::Assoc::func() +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.qualified.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.qualified.stderr new file mode 100644 index 0000000000000..10e467da9521a --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.qualified.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/assoc-type-const-bound-usage-1.rs:23:43 + | +LL | fn qualified() -> Type<{ ::Assoc::func() }> { + | ^ the trait `Trait` is not implemented for `T` + | +help: consider further restricting this bound + | +LL | fn qualified() -> Type<{ ::Assoc::func() }> { + | +++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs new file mode 100644 index 0000000000000..2190fa337b49f --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs @@ -0,0 +1,27 @@ +// FIXME(effects): Collapse the revisions into one once we support `::Proj`. +// revisions: unqualified qualified +//[unqualified] check-pass +//[qualified] known-bug: unknown + +#![feature(const_trait_impl, effects, generic_const_exprs)] +#![allow(incomplete_features)] + +#[const_trait] +trait Trait { + type Assoc: ~const Trait; + fn func() -> i32; +} + +struct Type; + +#[cfg(unqualified)] +fn unqualified() -> Type<{ T::Assoc::func() }> { + Type +} + +#[cfg(qualified)] +fn qualified() -> Type<{ ::Assoc::func() }> { + Type +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs deleted file mode 100644 index 16b717bc18131..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs +++ /dev/null @@ -1,15 +0,0 @@ -// known-bug: #110395 -// FIXME check-pass -#![feature(const_trait_impl, effects)] - -#[const_trait] -trait Foo { - type Assoc: ~const Foo; - fn foo() {} -} - -const fn foo() { - ::Assoc::foo(); -} - -fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr deleted file mode 100644 index 268e337ee93e6..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error: `~const` is not allowed here - --> $DIR/assoc-type-const-bound-usage.rs:7:17 - | -LL | type Assoc: ~const Foo; - | ^^^^^^ - | - = note: this item cannot have `~const` trait bounds - -error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/assoc-type-const-bound-usage.rs:12:6 - | -LL | ::Assoc::foo(); - | ^ the trait `Foo` is not implemented for `T` - | -help: consider further restricting this bound - | -LL | const fn foo() { - | +++++ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs index 96790a87311dd..886fa6577d76c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs @@ -1,29 +1,43 @@ -// known-bug: #110395 +// FIXME(effects): Replace `Add` with `std::ops::Add` once the latter a `#[const_trait]` again. +#![feature(const_trait_impl, effects)] -#![feature(const_trait_impl)] +#[const_trait] +trait Add { + type Output; + + fn add(self, other: Rhs) -> Self::Output; +} + +impl const Add for i32 { + type Output = Self; + + fn add(self, other: Self) -> Self::Output { + self + other + } +} struct NonConstAdd(i32); -impl std::ops::Add for NonConstAdd { +impl Add for NonConstAdd { type Output = Self; fn add(self, rhs: Self) -> Self { - NonConstAdd(self.0 + rhs.0) + NonConstAdd(self.0.add(rhs.0)) } } #[const_trait] trait Foo { - type Bar: ~const std::ops::Add; + type Bar: ~const Add; } impl const Foo for NonConstAdd { - type Bar = NonConstAdd; + type Bar = NonConstAdd; //~ ERROR the trait bound `NonConstAdd: ~const Add` is not satisfied } #[const_trait] trait Baz { - type Qux: std::ops::Add; + type Qux: Add; } impl const Baz for NonConstAdd { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr index 58ad1849d4fab..a9cae2a70be90 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr @@ -1,16 +1,16 @@ -error: `~const` is not allowed here - --> $DIR/assoc-type.rs:17:15 +error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied + --> $DIR/assoc-type.rs:35:16 | -LL | type Bar: ~const std::ops::Add; - | ^^^^^^ +LL | type Bar = NonConstAdd; + | ^^^^^^^^^^^ the trait `~const Add` is not implemented for `NonConstAdd` | - = note: this item cannot have `~const` trait bounds - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/assoc-type.rs:17:22 + = help: the trait `Add` is implemented for `NonConstAdd` +note: required by a bound in `Foo::Bar` + --> $DIR/assoc-type.rs:31:15 | -LL | type Bar: ~const std::ops::Add; - | ^^^^^^^^^^^^^ +LL | type Bar: ~const Add; + | ^^^^^^^^^^ required by this bound in `Foo::Bar` -error: aborting due to 2 previous errors +error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr index a54ba7a94b4aa..6b886e8851104 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -72,7 +72,11 @@ error: `~const` is not allowed here LL | type Type: ~const Trait; | ^^^^^^ | - = note: this item cannot have `~const` trait bounds +note: associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:25:5 + | +LL | type Type: ~const Trait; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `~const` is not allowed here --> $DIR/tilde-const-invalid-places.rs:25:33 @@ -80,7 +84,11 @@ error: `~const` is not allowed here LL | type Type: ~const Trait; | ^^^^^^ | - = note: this item cannot have `~const` trait bounds +note: associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:25:5 + | +LL | type Type: ~const Trait; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `~const` is not allowed here --> $DIR/tilde-const-invalid-places.rs:28:30 @@ -108,7 +116,11 @@ error: `~const` is not allowed here LL | type Type = (); | ^^^^^^ | - = note: this item cannot have `~const` trait bounds +note: associated types in non-const impls cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:34:5 + | +LL | type Type = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `~const` is not allowed here --> $DIR/tilde-const-invalid-places.rs:36:30 @@ -136,7 +148,11 @@ error: `~const` is not allowed here LL | type Type = (); | ^^^^^^ | - = note: this item cannot have `~const` trait bounds +note: inherent associated types cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:44:5 + | +LL | type Type = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `~const` is not allowed here --> $DIR/tilde-const-invalid-places.rs:46:30 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs new file mode 100644 index 0000000000000..4c383fe150674 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-trait-assoc-tys.rs @@ -0,0 +1,18 @@ +// check-pass +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Trait { + // FIXME(effects): `~const` bounds in trait associated types (excluding associated type bounds) + // don't look super useful. Should we forbid them again? + type Assoc; +} + +impl const Trait for () { + type Assoc = T; +} + +#[const_trait] +trait Bound {} + +fn main() {} From 4586fdce47e70ed4fe8568a6578bde2ed9faa31e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 12 Jan 2024 16:33:13 +0000 Subject: [PATCH 3/6] Taint `_` placeholder types --- .../rustc_hir_analysis/src/astconv/mod.rs | 8 +++++-- ...d-argument-mismatch-variance-ice-119867.rs | 13 ++++++++++ ...gument-mismatch-variance-ice-119867.stderr | 24 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/method-argument-mismatch-variance-ice-119867.rs create mode 100644 tests/ui/traits/method-argument-mismatch-variance-ice-119867.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 2886ec213201d..49887cfb6171d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2543,7 +2543,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i)) { infer_replacements.push((a.span, suggested_ty.to_string())); - return suggested_ty; + return Ty::new_error_with_message( + self.tcx(), + a.span, + suggested_ty.to_string(), + ); } } @@ -2561,7 +2565,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None) { infer_replacements.push((output.span, suggested_ty.to_string())); - suggested_ty + Ty::new_error_with_message(self.tcx(), output.span, suggested_ty.to_string()) } else { visitor.visit_ty(output); self.ast_ty_to_ty(output) diff --git a/tests/ui/traits/method-argument-mismatch-variance-ice-119867.rs b/tests/ui/traits/method-argument-mismatch-variance-ice-119867.rs new file mode 100644 index 0000000000000..4b7862abc91a9 --- /dev/null +++ b/tests/ui/traits/method-argument-mismatch-variance-ice-119867.rs @@ -0,0 +1,13 @@ +trait Deserialize { + fn deserialize(&self); +} + +struct ArchivedVec(T); + +impl Deserialize for ArchivedVec { + fn deserialize(s: _) {} + //~^ ERROR: `_` is not allowed within types on item signatures + //~| ERROR: has a `&self` declaration in the trait, but not in the impl +} + +fn main() {} diff --git a/tests/ui/traits/method-argument-mismatch-variance-ice-119867.stderr b/tests/ui/traits/method-argument-mismatch-variance-ice-119867.stderr new file mode 100644 index 0000000000000..e63cc522dd13a --- /dev/null +++ b/tests/ui/traits/method-argument-mismatch-variance-ice-119867.stderr @@ -0,0 +1,24 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/method-argument-mismatch-variance-ice-119867.rs:8:23 + | +LL | fn deserialize(s: _) {} + | ^ not allowed in type signatures + | +help: try replacing `_` with the type in the corresponding trait method signature + | +LL | fn deserialize(s: &ArchivedVec) {} + | ~~~~~~~~~~~~~~~ + +error[E0186]: method `deserialize` has a `&self` declaration in the trait, but not in the impl + --> $DIR/method-argument-mismatch-variance-ice-119867.rs:8:5 + | +LL | fn deserialize(&self); + | ---------------------- `&self` used in trait +... +LL | fn deserialize(s: _) {} + | ^^^^^^^^^^^^^^^^^^^^ expected `&self` in impl + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0121, E0186. +For more information about an error, try `rustc --explain E0121`. From 322694ed56461d36c05673a2644cbd4a44db5259 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Jan 2024 16:48:02 +0000 Subject: [PATCH 4/6] Remove unused ErrorReporting variant from overflow handling --- compiler/rustc_middle/src/traits/mod.rs | 3 --- compiler/rustc_middle/src/traits/select.rs | 2 -- .../src/traits/error_reporting/type_err_ctxt_ext.rs | 3 --- .../src/traits/query/evaluate_obligation.rs | 2 -- compiler/rustc_trait_selection/src/traits/select/mod.rs | 8 +++----- src/librustdoc/clean/blanket_impl.rs | 1 - 6 files changed, 3 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index af601a0d702ed..bebee8df10e86 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -611,9 +611,6 @@ pub enum SelectionError<'tcx> { NotConstEvaluatable(NotConstEvaluatable), /// Exceeded the recursion depth during type projection. Overflow(OverflowError), - /// Signaling that an error has already been emitted, to avoid - /// multiple errors being shown. - ErrorReporting, /// Computing an opaque type's hidden type caused an error (e.g. a cycle error). /// We can thus not know whether the hidden type implements an auto trait, so /// we should not presume anything about it. diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 734c2b61c07fc..64f4af08e12ed 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -302,7 +302,6 @@ impl EvaluationResult { pub enum OverflowError { Error(ErrorGuaranteed), Canonical, - ErrorReporting, } impl From for OverflowError { @@ -318,7 +317,6 @@ impl<'tcx> From for SelectionError<'tcx> { match overflow_error { OverflowError::Error(e) => SelectionError::Overflow(OverflowError::Error(e)), OverflowError::Canonical => SelectionError::Overflow(OverflowError::Canonical), - OverflowError::ErrorReporting => SelectionError::ErrorReporting, } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 47a700805fa5c..e33414aa587a6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -947,9 +947,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { Overflow(_) => { bug!("overflow should be handled before the `report_selection_error` path"); } - SelectionError::ErrorReporting => { - bug!("ErrorReporting Overflow should not reach `report_selection_err` call") - } }; self.note_obligation_cause(&mut err, &obligation); diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index 31e34096fb003..4c0c57377e02a 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -116,11 +116,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { r, ) } - OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr, OverflowError::Error(_) => EvaluationResult::EvaluatedToErr, }) } - Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr, Err(OverflowError::Error(_)) => EvaluationResult::EvaluatedToErr, } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 61fe2c8efe364..6a6adcbb680ea 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -14,9 +14,9 @@ use super::util; use super::util::closure_trait_ref_and_return_type; use super::wf; use super::{ - ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation, - ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation, - Selection, SelectionError, SelectionResult, TraitQueryMode, + ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation, ObligationCause, + ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation, Selection, + SelectionError, SelectionResult, TraitQueryMode, }; use crate::infer::{InferCtxt, InferOk, TypeFreshener}; @@ -496,7 +496,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } Ok(_) => Ok(None), Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)), - Err(OverflowError::ErrorReporting) => Err(ErrorReporting), Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))), }) .flat_map(Result::transpose) @@ -1233,7 +1232,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(Some(c)) => self.evaluate_candidate(stack, &c), Ok(None) => Ok(EvaluatedToAmbig), Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical), - Err(ErrorReporting) => Err(OverflowError::ErrorReporting), Err(..) => Ok(EvaluatedToErr), } } diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 4da85885d67cf..47cfe651e319d 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -81,7 +81,6 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { match infcx.evaluate_obligation(&obligation) { Ok(eval_result) if eval_result.may_apply() => {} Err(traits::OverflowError::Canonical) => {} - Err(traits::OverflowError::ErrorReporting) => {} _ => continue 'blanket_impls, } } From 51afc0922cc8b273fe8fb96ddcd190b307bad4b4 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Fri, 12 Jan 2024 15:51:18 -0500 Subject: [PATCH 5/6] fix typo in `fn()` docs --- library/core/src/primitive_docs.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index bd2851a26fb8c..267d9b44ad765 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1605,9 +1605,9 @@ mod prim_ref {} /// type in the function pointer to the type at the function declaration, and the return value is /// [`transmute`d][mem::transmute] from the type in the declaration to the type in the /// pointer. All the usual caveats and concerns around transmutation apply; for instance, if the -/// function expects a `NonNullI32` and the function pointer uses the ABI-compatible type -/// `Option`, and the value used for the argument is `None`, then this call is Undefined -/// Behavior since transmuting `None::` to `NonNullI32` violates the non-null +/// function expects a `NonZeroI32` and the function pointer uses the ABI-compatible type +/// `Option`, and the value used for the argument is `None`, then this call is Undefined +/// Behavior since transmuting `None::` to `NonZeroI32` violates the non-zero /// requirement. /// /// #### Requirements concerning target features From 41e224b1bc09d4b6528924933d66518bdbc0ef59 Mon Sep 17 00:00:00 2001 From: beepster4096 <19316085+beepster4096@users.noreply.github.com> Date: Fri, 12 Jan 2024 23:05:07 -0800 Subject: [PATCH 6/6] allow system abi to be variadic --- compiler/rustc_hir_analysis/src/lib.rs | 3 ++- compiler/rustc_metadata/src/native_libs.rs | 16 ++++++++++++++-- compiler/rustc_target/src/abi/call/mod.rs | 4 ++-- compiler/rustc_target/src/spec/abi/mod.rs | 3 ++- compiler/rustc_target/src/spec/mod.rs | 8 ++++++-- compiler/rustc_ty_utils/src/abi.rs | 6 +++--- tests/ui/c-variadic/variadic-ffi-2.rs | 5 ++++- tests/ui/c-variadic/variadic-ffi-2.stderr | 2 +- 8 files changed, 34 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 81d8982eb1574..44bb30017e9f8 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -116,7 +116,8 @@ use rustc_hir::def::DefKind; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { - const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `aapcs`, `win64`, `sysv64` or `efiapi`"; + const CONVENTIONS_UNSTABLE: &str = + "`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`"; const CONVENTIONS_STABLE: &str = "`C` or `cdecl`"; const UNSTABLE_EXPLAIN: &str = "using calling conventions other than `C` or `cdecl` for varargs functions is unstable"; diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index a639a887544e1..efb6406b05b13 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -520,11 +520,23 @@ impl<'tcx> Collector<'tcx> { ) -> DllImport { let span = self.tcx.def_span(item); + // this logic is similar to `Target::adjust_abi` (in rustc_target/src/spec/mod.rs) but errors on unsupported inputs let calling_convention = if self.tcx.sess.target.arch == "x86" { match abi { Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C, - Abi::Stdcall { .. } | Abi::System { .. } => { - DllCallingConvention::Stdcall(self.i686_arg_list_size(item)) + Abi::Stdcall { .. } => DllCallingConvention::Stdcall(self.i686_arg_list_size(item)), + // On Windows, `extern "system"` behaves like msvc's `__stdcall`. + // `__stdcall` only applies on x86 and on non-variadic functions: + // https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170 + Abi::System { .. } => { + let c_variadic = + self.tcx.type_of(item).instantiate_identity().fn_sig(self.tcx).c_variadic(); + + if c_variadic { + DllCallingConvention::C + } else { + DllCallingConvention::Stdcall(self.i686_arg_list_size(item)) + } } Abi::Fastcall { .. } => { DllCallingConvention::Fastcall(self.i686_arg_list_size(item)) diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index fafc10e71635a..1c83039047e05 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -840,7 +840,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "sparc" => sparc::compute_abi_info(cx, self), "sparc64" => sparc64::compute_abi_info(cx, self), "nvptx64" => { - if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::PtxKernel { + if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::PtxKernel { nvptx64::compute_ptx_kernel_abi_info(cx, self) } else { nvptx64::compute_abi_info(self) @@ -849,7 +849,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "hexagon" => hexagon::compute_abi_info(self), "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self), "wasm32" | "wasm64" => { - if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::Wasm { + if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::Wasm { wasm::compute_wasm_abi_info(self) } else { wasm::compute_c_abi_info(cx, self) diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs index 4c1f0c01a0411..1a0aa6f0c4a2e 100644 --- a/compiler/rustc_target/src/spec/abi/mod.rs +++ b/compiler/rustc_target/src/spec/abi/mod.rs @@ -70,15 +70,16 @@ impl Abi { // * C and Cdecl obviously support varargs. // * C can be based on Aapcs, SysV64 or Win64, so they must support varargs. // * EfiApi is based on Win64 or C, so it also supports it. + // * System falls back to C for functions with varargs. // // * Stdcall does not, because it would be impossible for the callee to clean // up the arguments. (callee doesn't know how many arguments are there) // * Same for Fastcall, Vectorcall and Thiscall. - // * System can become Stdcall, so is also a no-no. // * Other calling conventions are related to hardware or the compiler itself. match self { Self::C { .. } | Self::Cdecl { .. } + | Self::System { .. } | Self::Aapcs { .. } | Self::Win64 { .. } | Self::SysV64 { .. } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 9d25388b90fd0..3054d01e035f6 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2399,10 +2399,14 @@ impl DerefMut for Target { impl Target { /// Given a function ABI, turn it into the correct ABI for this target. - pub fn adjust_abi(&self, abi: Abi) -> Abi { + pub fn adjust_abi(&self, abi: Abi, c_variadic: bool) -> Abi { match abi { Abi::C { .. } => self.default_adjusted_cabi.unwrap_or(abi), - Abi::System { unwind } if self.is_like_windows && self.arch == "x86" => { + + // On Windows, `extern "system"` behaves like msvc's `__stdcall`. + // `__stdcall` only applies on x86 and on non-variadic functions: + // https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170 + Abi::System { unwind } if self.is_like_windows && self.arch == "x86" && !c_variadic => { Abi::Stdcall { unwind } } Abi::System { unwind } => Abi::C { unwind }, diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 2772831e731ec..6e8293dac312a 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -228,9 +228,9 @@ fn fn_sig_for_fn_abi<'tcx>( } #[inline] -fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { +fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv { use rustc_target::spec::abi::Abi::*; - match tcx.sess.target.adjust_abi(abi) { + match tcx.sess.target.adjust_abi(abi, c_variadic) { RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust, // This is intentionally not using `Conv::Cold`, as that has to preserve @@ -488,7 +488,7 @@ fn fn_abi_new_uncached<'tcx>( ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { let sig = cx.tcx.normalize_erasing_late_bound_regions(cx.param_env, sig); - let conv = conv_from_spec_abi(cx.tcx(), sig.abi); + let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic); let mut inputs = sig.inputs(); let extra_args = if sig.abi == RustCall { diff --git a/tests/ui/c-variadic/variadic-ffi-2.rs b/tests/ui/c-variadic/variadic-ffi-2.rs index 67a0a9a1dec3d..a412a58d7c59c 100644 --- a/tests/ui/c-variadic/variadic-ffi-2.rs +++ b/tests/ui/c-variadic/variadic-ffi-2.rs @@ -3,10 +3,13 @@ fn baz(f: extern "stdcall" fn(usize, ...)) { //~^ ERROR: C-variadic function must have a compatible calling convention, - // like C, cdecl, aapcs, win64, sysv64 or efiapi + // like C, cdecl, system, aapcs, win64, sysv64 or efiapi f(22, 44); } +fn system(f: extern "system" fn(usize, ...)) { + f(22, 44); +} fn aapcs(f: extern "aapcs" fn(usize, ...)) { f(22, 44); } diff --git a/tests/ui/c-variadic/variadic-ffi-2.stderr b/tests/ui/c-variadic/variadic-ffi-2.stderr index d0ca7034ba1c1..fbf273b1f1dbf 100644 --- a/tests/ui/c-variadic/variadic-ffi-2.stderr +++ b/tests/ui/c-variadic/variadic-ffi-2.stderr @@ -1,4 +1,4 @@ -error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `aapcs`, `win64`, `sysv64` or `efiapi` +error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` --> $DIR/variadic-ffi-2.rs:4:11 | LL | fn baz(f: extern "stdcall" fn(usize, ...)) {