From 84408ca9a3e7d1a49e2260902e75568f9e1d5d1a Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Wed, 15 Dec 2021 01:40:08 +0000 Subject: [PATCH 1/9] Point at type when a `static` `#[global_allocator]` doesn't `impl` `GlobalAlloc` --- .../src/global_allocator.rs | 22 ++++++++++--------- src/test/ui/allocator/not-an-allocator.stderr | 16 +++++++------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index a433876147f8d..36cfbba45dacc 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -26,14 +26,14 @@ pub fn expand( // Allow using `#[global_allocator]` on an item statement // FIXME - if we get deref patterns, use them to reduce duplication here - let (item, is_stmt) = match &item { + let (item, is_stmt, ty_span) = match &item { Annotatable::Item(item) => match item.kind { - ItemKind::Static(..) => (item, false), + ItemKind::Static(ref ty, ..) => (item, false, ecx.with_def_site_ctxt(ty.span)), _ => return not_static(), }, Annotatable::Stmt(stmt) => match &stmt.kind { StmtKind::Item(item_) => match item_.kind { - ItemKind::Static(..) => (item_, true), + ItemKind::Static(ref ty, ..) => (item_, true, ecx.with_def_site_ctxt(ty.span)), _ => return not_static(), }, _ => return not_static(), @@ -43,13 +43,14 @@ pub fn expand( // Generate a bunch of new items using the AllocFnFactory let span = ecx.with_def_site_ctxt(item.span); - let f = AllocFnFactory { span, kind: AllocatorKind::Global, global: item.ident, cx: ecx }; + let f = + AllocFnFactory { span, ty_span, kind: AllocatorKind::Global, global: item.ident, cx: ecx }; // Generate item statements for the allocator methods. let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect(); // Generate anonymous constant serving as container for the allocator methods. - let const_ty = ecx.ty(span, TyKind::Tup(Vec::new())); + let const_ty = ecx.ty(ty_span, TyKind::Tup(Vec::new())); let const_body = ecx.expr_block(ecx.block(span, stmts)); let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body); let const_item = if is_stmt { @@ -64,6 +65,7 @@ pub fn expand( struct AllocFnFactory<'a, 'b> { span: Span, + ty_span: Span, kind: AllocatorKind, global: Ident, cx: &'b ExtCtxt<'a>, @@ -97,18 +99,18 @@ impl AllocFnFactory<'_, '_> { self.attrs(), kind, ); - self.cx.stmt_item(self.span, item) + self.cx.stmt_item(self.ty_span, item) } fn call_allocator(&self, method: Symbol, mut args: Vec>) -> P { let method = self.cx.std_path(&[sym::alloc, sym::GlobalAlloc, method]); - let method = self.cx.expr_path(self.cx.path(self.span, method)); - let allocator = self.cx.path_ident(self.span, self.global); + let method = self.cx.expr_path(self.cx.path(self.ty_span, method)); + let allocator = self.cx.path_ident(self.ty_span, self.global); let allocator = self.cx.expr_path(allocator); - let allocator = self.cx.expr_addr_of(self.span, allocator); + let allocator = self.cx.expr_addr_of(self.ty_span, allocator); args.insert(0, allocator); - self.cx.expr_call(self.span, method, args) + self.cx.expr_call(self.ty_span, method, args) } fn attrs(&self) -> Vec { diff --git a/src/test/ui/allocator/not-an-allocator.stderr b/src/test/ui/allocator/not-an-allocator.stderr index e7a9ce94af4d9..c0f6118a9f163 100644 --- a/src/test/ui/allocator/not-an-allocator.stderr +++ b/src/test/ui/allocator/not-an-allocator.stderr @@ -1,40 +1,40 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:2:1 + --> $DIR/not-an-allocator.rs:2:11 | LL | #[global_allocator] | ------------------- in this procedural macro expansion LL | static A: usize = 0; - | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:2:1 + --> $DIR/not-an-allocator.rs:2:11 | LL | #[global_allocator] | ------------------- in this procedural macro expansion LL | static A: usize = 0; - | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:2:1 + --> $DIR/not-an-allocator.rs:2:11 | LL | #[global_allocator] | ------------------- in this procedural macro expansion LL | static A: usize = 0; - | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:2:1 + --> $DIR/not-an-allocator.rs:2:11 | LL | #[global_allocator] | ------------------- in this procedural macro expansion LL | static A: usize = 0; - | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) From 9622a4277698a055c2f136834afa30e94bf93071 Mon Sep 17 00:00:00 2001 From: chordtoll Date: Sun, 9 Jan 2022 23:35:54 -0800 Subject: [PATCH 2/9] Only suggest char literal for single-character strings --- compiler/rustc_infer/src/infer/error_reporting/mod.rs | 2 +- src/test/ui/inference/char-as-str-multi.rs | 3 ++- src/test/ui/inference/char-as-str-multi.stderr | 10 +++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index f0c73d0c2f369..69b610feb7ca5 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2068,7 +2068,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"')) { - if code.chars().nth(1).is_none() { + if code.chars().count() == 1 { err.span_suggestion( span, "if you meant to write a `char` literal, use single quotes", diff --git a/src/test/ui/inference/char-as-str-multi.rs b/src/test/ui/inference/char-as-str-multi.rs index 21bbc6f20b294..c29a15025a9c2 100644 --- a/src/test/ui/inference/char-as-str-multi.rs +++ b/src/test/ui/inference/char-as-str-multi.rs @@ -1,6 +1,7 @@ -// When a MULTI-character string literal is used where a char should be, +// When a MULTI/NO-character string literal is used where a char should be, // DO NOT suggest changing to single quotes. fn main() { let _: char = "foo"; //~ ERROR mismatched types + let _: char = ""; //~ ERROR mismatched types } diff --git a/src/test/ui/inference/char-as-str-multi.stderr b/src/test/ui/inference/char-as-str-multi.stderr index c3ba17a5579ad..297ca2b548f71 100644 --- a/src/test/ui/inference/char-as-str-multi.stderr +++ b/src/test/ui/inference/char-as-str-multi.stderr @@ -6,6 +6,14 @@ LL | let _: char = "foo"; | | | expected due to this -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/char-as-str-multi.rs:6:19 + | +LL | let _: char = ""; + | ---- ^^ expected `char`, found `&str` + | | + | expected due to this + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. From ac02fcc4d8b5cc0f1d727b30f8f2142dc9bacc8e Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 22 Jan 2022 14:50:08 +0000 Subject: [PATCH 3/9] Use `NtCreateFile` instead of `NtOpenFile` to open a file --- library/std/src/fs.rs | 2 +- library/std/src/sys/windows/c.rs | 12 +++++++++--- library/std/src/sys/windows/fs.rs | 11 ++++++++--- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 9d6b2fe8c25d8..4751995556422 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2044,7 +2044,7 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// /// This function currently corresponds to `openat`, `fdopendir`, `unlinkat` and `lstat` functions /// on Unix (except for macOS before version 10.10 and REDOX) and the `CreateFileW`, -/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtOpenFile` functions on +/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile` functions on /// Windows. Note that, this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 09d3661e4fd52..dfcd6124454a4 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -88,6 +88,7 @@ pub const FILE_SHARE_DELETE: DWORD = 0x4; pub const FILE_SHARE_READ: DWORD = 0x1; pub const FILE_SHARE_WRITE: DWORD = 0x2; +pub const FILE_OPEN: ULONG = 0x00000001; pub const FILE_OPEN_REPARSE_POINT: ULONG = 0x200000; pub const OBJ_DONT_REPARSE: ULONG = 0x1000; @@ -1228,15 +1229,20 @@ compat_fn! { compat_fn! { "ntdll": - pub fn NtOpenFile( + pub fn NtCreateFile( FileHandle: *mut HANDLE, DesiredAccess: ACCESS_MASK, ObjectAttributes: *const OBJECT_ATTRIBUTES, IoStatusBlock: *mut IO_STATUS_BLOCK, + AllocationSize: *mut i64, + FileAttributes: ULONG, ShareAccess: ULONG, - OpenOptions: ULONG + CreateDisposition: ULONG, + CreateOptions: ULONG, + EaBuffer: *mut c_void, + EaLength: ULONG ) -> NTSTATUS { - panic!("`NtOpenFile` not available"); + panic!("`NtCreateFile` not available"); } pub fn RtlNtStatusToDosError( Status: NTSTATUS diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index dd21c6b43891f..a7fb7c32f7cbe 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -712,11 +712,11 @@ impl<'a> Iterator for DirBuffIter<'a> { /// Open a link relative to the parent directory, ensure no symlinks are followed. fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result { - // This is implemented using the lower level `NtOpenFile` function as + // This is implemented using the lower level `NtCreateFile` function as // unfortunately opening a file relative to a parent is not supported by // win32 functions. It is however a fundamental feature of the NT kernel. // - // See https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntopenfile + // See https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntcreatefile unsafe { let mut handle = ptr::null_mut(); let mut io_status = c::IO_STATUS_BLOCK::default(); @@ -732,14 +732,19 @@ fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result< Attributes: ATTRIBUTES.load(Ordering::Relaxed), ..c::OBJECT_ATTRIBUTES::default() }; - let status = c::NtOpenFile( + let status = c::NtCreateFile( &mut handle, access, &object, &mut io_status, + crate::ptr::null_mut(), + 0, c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE, + c::FILE_OPEN, // If `name` is a symlink then open the link rather than the target. c::FILE_OPEN_REPARSE_POINT, + crate::ptr::null_mut(), + 0, ); // Convert an NTSTATUS to the more familiar Win32 error codes (aka "DosError") if c::nt_success(status) { From c965d0eaf2cecdd3b72a04b9e34fd4eb5d837113 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 7 Feb 2022 09:17:44 +0100 Subject: [PATCH 4/9] add fut/back compat tests for implied trait bounds --- .../hrlt-implied-trait-bounds-guard.rs | 51 +++++++++++++++++++ .../hrlt-implied-trait-bounds-guard.stderr | 12 +++++ .../hrlt-implied-trait-bounds-roundtrip.rs | 35 +++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs create mode 100644 src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.stderr create mode 100644 src/test/ui/implied-bounds/hrlt-implied-trait-bounds-roundtrip.rs diff --git a/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs new file mode 100644 index 0000000000000..d79f63d45975d --- /dev/null +++ b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs @@ -0,0 +1,51 @@ +// A test exploiting the bug behind #25860 except with +// implied trait bounds which currently don't exist, +// +// please ping @lcnr if your changes end up causing `badboi` to compile. +use std::marker::PhantomData; +struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>) +where + T: Convert<'a, 'b>; + +trait Convert<'a, 'b>: Sized { + fn cast(&'a self) -> &'b Self; +} +impl<'long: 'short, 'short, T> Convert<'long, 'short> for T { + fn cast(&'long self) -> &'short T { + self + } +} + +// This function will compile once we add implied trait bounds. +// +// If we're not careful with our impl, the transformations +// in `bad` would succeed, which is unsound ✨ +// +// FIXME: the error is pretty bad, this should say +// +// `T: Convert<'in_, 'out>` is not implemented +// +// help: needed by `Foo<'in_, 'out, T>` +fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ T) -> &'out T { + //~^ ERROR lifetime mismatch + sadness.cast() +} + +fn bad<'short, T>(value: &'short T) -> &'static T { + let x: for<'in_, 'out> fn(Foo<'in_, 'out, T>, &'in_ T) -> &'out T = badboi; + let x: for<'out> fn(Foo<'short, 'out, T>, &'short T) -> &'out T = x; + let x: for<'out> fn(Foo<'static, 'out, T>, &'short T) -> &'out T = x; + let x: fn(Foo<'static, 'static, T>, &'short T) -> &'static T = x; + x(Foo(PhantomData), value) +} + +// Use `bad` to cause a segfault. +fn main() { + let mut outer: Option<&'static u32> = Some(&3); + let static_ref: &'static &'static u32 = match outer { + Some(ref reference) => bad(reference), + None => unreachable!(), + }; + outer = None; + println!("{}", static_ref); +} diff --git a/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.stderr b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.stderr new file mode 100644 index 0000000000000..b020ea64bf46e --- /dev/null +++ b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.stderr @@ -0,0 +1,12 @@ +error[E0623]: lifetime mismatch + --> $DIR/hrlt-implied-trait-bounds-guard.rs:29:29 + | +LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ T) -> &'out T { + | ^^^^^^^^^^^^^^^^^^ ------- + | | + | this parameter and the return type are declared with different lifetimes... + | ...but data from `x` is returned here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-roundtrip.rs b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-roundtrip.rs new file mode 100644 index 0000000000000..69847d6a8bb53 --- /dev/null +++ b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-roundtrip.rs @@ -0,0 +1,35 @@ +// check-pass +struct Foo<'a>(&'a ()) +where + (): Trait<'a>; + +trait Trait<'a> { + fn id(value: &'a T) -> &'static T; +} + +impl Trait<'static> for () { + fn id(value: &'static T) -> &'static T { + value + } +} + +fn could_use_implied_bounds<'a, T>(_: Foo<'a>, x: &'a T) -> &'static T +where + (): Trait<'a>, // This could be an implied bound +{ + <()>::id(x) +} + +fn main() { + let bar: for<'a, 'b> fn(Foo<'a>, &'b ()) = |_, _| {}; + + // If `could_use_implied_bounds` were to use implied bounds, + // keeping 'a late-bound, then we could assign that function + // to this variable. + let bar: for<'a> fn(Foo<'a>, &'a ()) = bar; + + // In this case, the subtyping relation here would be unsound, + // allowing us to transmute lifetimes. This currently compiles + // because we incorrectly deal with implied bounds inside of binders. + let _bar: for<'a, 'b> fn(Foo<'a>, &'b ()) = bar; +} From 3602e0e262275c898966c45553c406c4873472fe Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Fri, 14 Jan 2022 20:51:30 -0500 Subject: [PATCH 5/9] Don't match any projection predicates when the obligation has inference types or consts in GAT substs --- .../src/traits/error_reporting/suggestions.rs | 4 +-- .../src/traits/select/mod.rs | 10 +++++++ .../generic-associated-types/issue-91762.rs | 30 +++++++++++++++++++ .../issue-91762.stderr | 22 ++++++++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/generic-associated-types/issue-91762.rs create mode 100644 src/test/ui/generic-associated-types/issue-91762.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6634f3e364d32..9a7d06ef6406d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2470,8 +2470,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let projection_ty = ty::ProjectionTy { // `T` substs: self.tcx.mk_substs_trait( - trait_pred.self_ty().skip_binder(), - self.fresh_substs_for_item(span, item_def_id), + trait_ref.self_ty().skip_binder(), + &self.fresh_substs_for_item(span, item_def_id)[1..], ), // `Future::Output` item_def_id, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 47427395b93b3..562535b0fea39 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1521,6 +1521,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { infer_predicate.projection_ty }; + // If the obligation contains any inference types or consts in associated + // type substs, then we don't match any projection candidates against it. + // This isn't really correct, but otherwise we can end up in a case where + // we constrain inference variables by selecting a single predicate, when + // we need to stay general. See issue #91762. + let (_, predicate_own_substs) = + obligation.predicate.trait_ref_and_own_substs(self.infcx.tcx); + if predicate_own_substs.iter().any(|g| g.has_infer_types_or_consts()) { + return false; + } self.infcx .at(&obligation.cause, obligation.param_env) .sup(obligation.predicate, infer_projection) diff --git a/src/test/ui/generic-associated-types/issue-91762.rs b/src/test/ui/generic-associated-types/issue-91762.rs new file mode 100644 index 0000000000000..e39a127abfd81 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91762.rs @@ -0,0 +1,30 @@ +// check-fail + +// FIXME(generic_associated_types): We almost certaintly want this to pass, but +// it's particularly difficult currently, because we need a way of specifying +// that `::With = Self` without using that when we have +// a `U`. See `/~https://github.com/rust-lang/rust/pull/92728` for a (hacky) +// solution. This might be better to just wait for Chalk. + +#![feature(generic_associated_types)] + +pub trait Functor { + type With; + + fn fmap(this: Self::With) -> Self::With; +} + +pub trait FunctorExt: Sized { + type Base: Functor = Self>; + + fn fmap(self) { + let arg: ::With; + let ret: ::With; + + arg = self; + ret = ::fmap(arg); + //~^ mismatched types + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-91762.stderr b/src/test/ui/generic-associated-types/issue-91762.stderr new file mode 100644 index 0000000000000..e177e151d8aac --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91762.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/issue-91762.rs:25:45 + | +LL | / pub trait FunctorExt: Sized { +LL | | type Base: Functor = Self>; +LL | | +LL | | fn fmap(self) { +... | +LL | | ret = ::fmap(arg); + | | ^^^ expected associated type, found type parameter `Self` +LL | | +LL | | } +LL | | } + | |_- this type parameter + | + = note: expected associated type `<>::Base as Functor>::With<_>` + found type parameter `Self` + = note: you might be missing a type parameter or trait bound + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 7ad48bd4e22aaffa5ac32809b9196fab9c04de2c Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Fri, 14 Jan 2022 21:21:40 -0500 Subject: [PATCH 6/9] Change inference var check to be in project_type --- .../src/traits/error_reporting/suggestions.rs | 2 +- .../src/traits/project.rs | 10 ++++++++ .../src/traits/select/mod.rs | 10 -------- .../generic-associated-types/issue-74824.rs | 1 + .../issue-74824.stderr | 11 +++++++-- .../generic-associated-types/issue-91762.rs | 2 +- .../issue-91762.stderr | 23 ++++--------------- 7 files changed, 27 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 9a7d06ef6406d..b594723aa0bd2 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2470,7 +2470,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let projection_ty = ty::ProjectionTy { // `T` substs: self.tcx.mk_substs_trait( - trait_ref.self_ty().skip_binder(), + trait_pred.self_ty().skip_binder(), &self.fresh_substs_for_item(span, item_def_id)[1..], ), // `Future::Output` diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 5e7d4c8b415c3..36cc14610cb4b 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1073,6 +1073,16 @@ fn project<'cx, 'tcx>( return Ok(Projected::Progress(Progress::error(selcx.tcx()))); } + // If the obligation contains any inference types or consts in associated + // type substs, then we don't assemble any candidates. + // This isn't really correct, but otherwise we can end up in a case where + // we constrain inference variables by selecting a single predicate, when + // we need to stay general. See issue #91762. + let (_, predicate_own_substs) = obligation.predicate.trait_ref_and_own_substs(selcx.tcx()); + if predicate_own_substs.iter().any(|g| g.has_infer_types_or_consts()) { + return Err(ProjectionError::TooManyCandidates); + } + let mut candidates = ProjectionCandidateSet::None; // Make sure that the following procedures are kept in order. ParamEnv diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 562535b0fea39..47427395b93b3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1521,16 +1521,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { infer_predicate.projection_ty }; - // If the obligation contains any inference types or consts in associated - // type substs, then we don't match any projection candidates against it. - // This isn't really correct, but otherwise we can end up in a case where - // we constrain inference variables by selecting a single predicate, when - // we need to stay general. See issue #91762. - let (_, predicate_own_substs) = - obligation.predicate.trait_ref_and_own_substs(self.infcx.tcx); - if predicate_own_substs.iter().any(|g| g.has_infer_types_or_consts()) { - return false; - } self.infcx .at(&obligation.cause, obligation.param_env) .sup(obligation.predicate, infer_projection) diff --git a/src/test/ui/generic-associated-types/issue-74824.rs b/src/test/ui/generic-associated-types/issue-74824.rs index 1bbf7aac5cdab..01f99fa448749 100644 --- a/src/test/ui/generic-associated-types/issue-74824.rs +++ b/src/test/ui/generic-associated-types/issue-74824.rs @@ -17,6 +17,7 @@ impl UnsafeCopy for T {} fn main() { let b = Box::new(42usize); let copy = <()>::copy(&b); + //~^ type annotations needed let raw_b = Box::deref(&b) as *const _; let raw_copy = Box::deref(©) as *const _; diff --git a/src/test/ui/generic-associated-types/issue-74824.stderr b/src/test/ui/generic-associated-types/issue-74824.stderr index 8517eb9fa2102..e7ebf5964ba41 100644 --- a/src/test/ui/generic-associated-types/issue-74824.stderr +++ b/src/test/ui/generic-associated-types/issue-74824.stderr @@ -27,6 +27,13 @@ help: consider restricting type parameter `T` LL | type Copy: Copy = Box; | +++++++++++++++++++ -error: aborting due to 2 previous errors +error[E0282]: type annotations needed + --> $DIR/issue-74824.rs:19:16 + | +LL | let copy = <()>::copy(&b); + | ^^^^^^^^^^ cannot infer type for type parameter `T` declared on the associated function `copy` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0282. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-91762.rs b/src/test/ui/generic-associated-types/issue-91762.rs index e39a127abfd81..b259a3c6e06bc 100644 --- a/src/test/ui/generic-associated-types/issue-91762.rs +++ b/src/test/ui/generic-associated-types/issue-91762.rs @@ -23,7 +23,7 @@ pub trait FunctorExt: Sized { arg = self; ret = ::fmap(arg); - //~^ mismatched types + //~^ type annotations needed } } diff --git a/src/test/ui/generic-associated-types/issue-91762.stderr b/src/test/ui/generic-associated-types/issue-91762.stderr index e177e151d8aac..a9c465cdd7ea2 100644 --- a/src/test/ui/generic-associated-types/issue-91762.stderr +++ b/src/test/ui/generic-associated-types/issue-91762.stderr @@ -1,22 +1,9 @@ -error[E0308]: mismatched types - --> $DIR/issue-91762.rs:25:45 +error[E0282]: type annotations needed + --> $DIR/issue-91762.rs:25:15 | -LL | / pub trait FunctorExt: Sized { -LL | | type Base: Functor = Self>; -LL | | -LL | | fn fmap(self) { -... | -LL | | ret = ::fmap(arg); - | | ^^^ expected associated type, found type parameter `Self` -LL | | -LL | | } -LL | | } - | |_- this type parameter - | - = note: expected associated type `<>::Base as Functor>::With<_>` - found type parameter `Self` - = note: you might be missing a type parameter or trait bound +LL | ret = ::fmap(arg); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the associated function `fmap` error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0282`. From af9e30a326b56bca01ef3a7694ab8a117d791885 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 7 Feb 2022 16:35:28 +0100 Subject: [PATCH 7/9] nit --- .../ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs index d79f63d45975d..d9de73a38efff 100644 --- a/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs +++ b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs @@ -1,7 +1,5 @@ // A test exploiting the bug behind #25860 except with -// implied trait bounds which currently don't exist, -// -// please ping @lcnr if your changes end up causing `badboi` to compile. +// implied trait bounds which currently don't exist without `-Zchalk`. use std::marker::PhantomData; struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>) where @@ -26,6 +24,8 @@ impl<'long: 'short, 'short, T> Convert<'long, 'short> for T { // `T: Convert<'in_, 'out>` is not implemented // // help: needed by `Foo<'in_, 'out, T>` +// +// Please ping @lcnr if your changes end up causing `badboi` to compile. fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ T) -> &'out T { //~^ ERROR lifetime mismatch sadness.cast() From 4eb5fe1f9c46776938274c9dcf941f736a74c06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 8 Feb 2022 11:10:44 +0200 Subject: [PATCH 8/9] :arrow_up: rust-analyzer --- src/tools/rust-analyzer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 9700addc82111..ba33054802360 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 9700addc82111200a2150b9a796f62dd8e600ddf +Subproject commit ba330548023607717295f0dfd61b72eda41aa9dd From 2b200727a322a3252e4077933aab91c39e74ef5b Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 8 Feb 2022 11:30:59 +0100 Subject: [PATCH 9/9] deduplicate `lcnr` in mailmap --- .mailmap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index ac221fa3a60e4..d72e6ebcb65fa 100644 --- a/.mailmap +++ b/.mailmap @@ -173,7 +173,7 @@ Kyle J Strand Kyle J Strand Kyle J Strand Laurențiu Nicola -lcnr +lcnr Lee Jeffery Lee Jeffery Lee Wondong Lennart Kudling