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/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 6fdfc8e39f10d..8d41497541a19 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2053,7 +2053,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/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 51b8c9aca78b3..65a18897b3915 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2473,7 +2473,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// `T`
substs: self.tcx.mk_substs_trait(
trait_pred.self_ty().skip_binder(),
- self.fresh_substs_for_item(span, item_def_id),
+ &self.fresh_substs_for_item(span, item_def_id)[1..],
),
// `Future::Output`
item_def_id,
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/library/std/src/fs.rs b/library/std/src/fs.rs
index 95e9064442634..0b65336a5a7da 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 fed655af87e63..cb83ee2469a1c 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) {
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 86115a9029465..f44ebfc0b296f 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1291,7 +1291,6 @@ def bootstrap(help_triggered):
env["BOOTSTRAP_PARENT_ID"] = str(os.getpid())
env["BOOTSTRAP_PYTHON"] = sys.executable
env["BUILD_DIR"] = build.build_dir
- env["RUSTC_BOOTSTRAP"] = '1'
if toml_path:
env["BOOTSTRAP_CONFIG"] = toml_path
if build.rustc_commit is not None:
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)
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
new file mode 100644
index 0000000000000..b259a3c6e06bc
--- /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);
+ //~^ type annotations needed
+ }
+}
+
+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..a9c465cdd7ea2
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-91762.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/issue-91762.rs:25:15
+ |
+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 E0282`.
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..d9de73a38efff
--- /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 without `-Zchalk`.
+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>`
+//
+// 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()
+}
+
+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;
+}
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`.
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