diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 2e86970bcfdc7..f933b9b161ca9 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2466,7 +2466,7 @@ pub enum ModKind { Unloaded, } -#[derive(Copy, Clone, Encodable, Decodable, Debug)] +#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)] pub struct ModSpans { /// `inner_span` covers the body of the module; for a file module, its the whole file. /// For an inline module, its the span inside the `{ ... }`, not including the curly braces. @@ -2474,12 +2474,6 @@ pub struct ModSpans { pub inject_use_span: Span, } -impl Default for ModSpans { - fn default() -> ModSpans { - ModSpans { inner_span: Default::default(), inject_use_span: Default::default() } - } -} - /// Foreign module declaration. /// /// E.g., `extern { .. }` or `extern "C" { .. }`. diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index 03ff5e5b3751f..05f059c89d5cd 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -126,13 +126,13 @@ impl SortedMap { /// Iterate over the keys, sorted #[inline] pub fn keys(&self) -> impl Iterator + ExactSizeIterator + DoubleEndedIterator { - self.data.iter().map(|&(ref k, _)| k) + self.data.iter().map(|(k, _)| k) } /// Iterate over values, sorted by key #[inline] pub fn values(&self) -> impl Iterator + ExactSizeIterator + DoubleEndedIterator { - self.data.iter().map(|&(_, ref v)| v) + self.data.iter().map(|(_, v)| v) } #[inline] @@ -222,7 +222,7 @@ impl SortedMap { K: Borrow, Q: Ord + ?Sized, { - self.data.binary_search_by(|&(ref x, _)| x.borrow().cmp(key)) + self.data.binary_search_by(|(x, _)| x.borrow().cmp(key)) } #[inline] @@ -300,7 +300,7 @@ impl FromIterator<(K, V)> for SortedMap { fn from_iter>(iter: T) -> Self { let mut data: Vec<(K, V)> = iter.into_iter().collect(); - data.sort_unstable_by(|&(ref k1, _), &(ref k2, _)| k1.cmp(k2)); + data.sort_unstable_by(|(k1, _), (k2, _)| k1.cmp(k2)); data.dedup_by(|&mut (ref k1, _), &mut (ref k2, _)| k1.cmp(k2) == Ordering::Equal); SortedMap { data } diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index e33323a779536..26cdf8a58f3fb 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -20,6 +20,10 @@ hir_analysis_lifetimes_or_bounds_mismatch_on_trait = .where_label = this `where` clause might not match the one in the trait .bounds_label = this bound might be missing in the impl +hir_analysis_async_trait_impl_should_be_async = + method `{$method_name}` should be async because the method from the trait is async + .trait_item_label = required because the trait method is async + hir_analysis_drop_impl_on_wrong_item = the `Drop` trait may only be implemented for local structs, enums, and unions .label = must be a struct, enum, or union in the current crate diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index c62e358e804ca..e2a0e436fd5e2 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2313,7 +2313,7 @@ impl FileWithAnnotatedLines { } // Find overlapping multiline annotations, put them at different depths - multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, usize::MAX - ml.line_end)); + multiline_annotations.sort_by_key(|(_, ml)| (ml.line_start, usize::MAX - ml.line_end)); for (_, ann) in multiline_annotations.clone() { for (_, a) in multiline_annotations.iter_mut() { // Move all other multiline annotations overlapping with this one diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index eb0506c459afa..518b5ec10f890 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -324,7 +324,7 @@ impl CodeSuggestion { // Account for the difference between the width of the current code and the // snippet being suggested, so that the *later* suggestions are correctly // aligned on the screen. - acc += len as isize - (cur_hi.col.0 - cur_lo.col.0) as isize; + acc += len - (cur_hi.col.0 - cur_lo.col.0) as isize; } prev_hi = cur_hi; prev_line = sf.get_line(prev_hi.line - 1); diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index 4f4e9a89fc741..6b9ce9a4599e2 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -67,6 +67,10 @@ pub(crate) fn compare_impl_method<'tcx>( return; } + if let Err(_) = compare_asyncness(tcx, impl_m, impl_m_span, trait_m, trait_item_span) { + return; + } + if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref) { return; @@ -323,6 +327,34 @@ fn compare_predicate_entailment<'tcx>( Ok(()) } +fn compare_asyncness<'tcx>( + tcx: TyCtxt<'tcx>, + impl_m: &ty::AssocItem, + impl_m_span: Span, + trait_m: &ty::AssocItem, + trait_item_span: Option, +) -> Result<(), ErrorGuaranteed> { + if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async { + match tcx.fn_sig(impl_m.def_id).skip_binder().output().kind() { + ty::Alias(ty::Opaque, ..) => { + // allow both `async fn foo()` and `fn foo() -> impl Future` + } + ty::Error(rustc_errors::ErrorGuaranteed { .. }) => { + // We don't know if it's ok, but at least it's already an error. + } + _ => { + return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync { + span: impl_m_span, + method_name: trait_m.name, + trait_item_span, + })); + } + }; + } + + Ok(()) +} + #[instrument(skip(tcx), level = "debug", ret)] pub fn collect_trait_impl_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index d9697c63c56e1..d383fcacb3a9c 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -51,6 +51,17 @@ pub struct LifetimesOrBoundsMismatchOnTrait { pub ident: Ident, } +#[derive(Diagnostic)] +#[diag(hir_analysis_async_trait_impl_should_be_async)] +pub struct AsyncTraitImplShouldBeAsync { + #[primary_span] + // #[label] + pub span: Span, + #[label(trait_item_label)] + pub trait_item_span: Option, + pub method_name: Symbol, +} + #[derive(Diagnostic)] #[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")] pub struct DropImplOnWrongItem { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ef98c4ba54cbd..29a6902ccb077 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1757,7 +1757,6 @@ impl<'a> State<'a> { self.print_qpath(qpath, true); self.popen(); if let Some(ddpos) = ddpos.as_opt_usize() { - let ddpos = ddpos as usize; self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p)); if ddpos != 0 { self.word_space(","); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 0103f58d0614c..5c0d5f32f0fd0 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -893,7 +893,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } else { - err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds")); + let ty_str = if ty_str.len() > 50 { + String::new() + } else { + format!("on `{ty_str}` ") + }; + err.span_label(span, format!( + "{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds" + )); } }; diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 684835d8c5c86..13f06fe747349 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -192,7 +192,7 @@ impl Mismatch { let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?; // If we're not in a "rustc_" crate, bail. - let Some(("rustc", slug_prefix)) = crate_name.split_once("_") else { return None }; + let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None }; let slug_name = slug.segments.first()?.ident.to_string(); if !slug_name.starts_with(slug_prefix) { diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index d8d476d3fefe2..8c22df7395f10 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -3,8 +3,8 @@ use std::ops::ControlFlow; use crate::ty::{ - visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst, - InferTy, Opaque, PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, + visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque, + PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, }; use rustc_data_structures::fx::FxHashMap; @@ -469,17 +469,6 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> { } } - Dynamic(dty, _, _) => { - for pred in *dty { - match pred.skip_binder() { - ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => { - // Okay - } - _ => return ControlFlow::Break(()), - } - } - } - Param(param) => { // FIXME: It would be nice to make this not use string manipulation, // but it's pretty hard to do this, since `ty::ParamTy` is missing diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 97485c4f57b12..3e45319431cec 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -132,15 +132,12 @@ use std::collections::hash_map::{Entry, OccupiedEntry}; use crate::MirPass; use rustc_data_structures::fx::FxHashMap; use rustc_index::bit_set::BitSet; +use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::{dump_mir, PassWhere}; use rustc_middle::mir::{ traversal, BasicBlock, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind, }; -use rustc_middle::mir::{ - visit::{MutVisitor, PlaceContext, Visitor}, - ProjectionElem, -}; use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::impls::MaybeLiveLocals; use rustc_mir_dataflow::{Analysis, ResultsCursor}; @@ -359,40 +356,45 @@ struct FilterInformation<'a, 'body, 'alloc, 'tcx> { // through these methods, and not directly. impl<'alloc> Candidates<'alloc> { /// Just `Vec::retain`, but the condition is inverted and we add debugging output - fn vec_remove_debug( + fn vec_filter_candidates( src: Local, v: &mut Vec, - mut f: impl FnMut(Local) -> bool, + mut f: impl FnMut(Local) -> CandidateFilter, at: Location, ) { v.retain(|dest| { let remove = f(*dest); - if remove { + if remove == CandidateFilter::Remove { trace!("eliminating {:?} => {:?} due to conflict at {:?}", src, dest, at); } - !remove + remove == CandidateFilter::Keep }); } - /// `vec_remove_debug` but for an `Entry` - fn entry_remove( + /// `vec_filter_candidates` but for an `Entry` + fn entry_filter_candidates( mut entry: OccupiedEntry<'_, Local, Vec>, p: Local, - f: impl FnMut(Local) -> bool, + f: impl FnMut(Local) -> CandidateFilter, at: Location, ) { let candidates = entry.get_mut(); - Self::vec_remove_debug(p, candidates, f, at); + Self::vec_filter_candidates(p, candidates, f, at); if candidates.len() == 0 { entry.remove(); } } - /// Removes all candidates `(p, q)` or `(q, p)` where `p` is the indicated local and `f(q)` is true. - fn remove_candidates_if(&mut self, p: Local, mut f: impl FnMut(Local) -> bool, at: Location) { + /// For all candidates `(p, q)` or `(q, p)` removes the candidate if `f(q)` says to do so + fn filter_candidates_by( + &mut self, + p: Local, + mut f: impl FnMut(Local) -> CandidateFilter, + at: Location, + ) { // Cover the cases where `p` appears as a `src` if let Entry::Occupied(entry) = self.c.entry(p) { - Self::entry_remove(entry, p, &mut f, at); + Self::entry_filter_candidates(entry, p, &mut f, at); } // And the cases where `p` appears as a `dest` let Some(srcs) = self.reverse.get_mut(&p) else { @@ -401,18 +403,31 @@ impl<'alloc> Candidates<'alloc> { // We use `retain` here to remove the elements from the reverse set if we've removed the // matching candidate in the forward set. srcs.retain(|src| { - if !f(*src) { + if f(*src) == CandidateFilter::Keep { return true; } let Entry::Occupied(entry) = self.c.entry(*src) else { return false; }; - Self::entry_remove(entry, *src, |dest| dest == p, at); + Self::entry_filter_candidates( + entry, + *src, + |dest| { + if dest == p { CandidateFilter::Remove } else { CandidateFilter::Keep } + }, + at, + ); false }); } } +#[derive(Copy, Clone, PartialEq, Eq)] +enum CandidateFilter { + Keep, + Remove, +} + impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { /// Filters the set of candidates to remove those that conflict. /// @@ -460,7 +475,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { for (i, statement) in data.statements.iter().enumerate().rev() { self.at = Location { block, statement_index: i }; self.live.seek_after_primary_effect(self.at); - self.get_statement_write_info(&statement.kind); + self.write_info.for_statement(&statement.kind, self.body); self.apply_conflicts(); } } @@ -469,80 +484,59 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { fn apply_conflicts(&mut self) { let writes = &self.write_info.writes; for p in writes { - self.candidates.remove_candidates_if( + let other_skip = self.write_info.skip_pair.and_then(|(a, b)| { + if a == *p { + Some(b) + } else if b == *p { + Some(a) + } else { + None + } + }); + self.candidates.filter_candidates_by( *p, - // It is possible that a local may be live for less than the - // duration of a statement This happens in the case of function - // calls or inline asm. Because of this, we also mark locals as - // conflicting when both of them are written to in the same - // statement. - |q| self.live.contains(q) || writes.contains(&q), + |q| { + if Some(q) == other_skip { + return CandidateFilter::Keep; + } + // It is possible that a local may be live for less than the + // duration of a statement This happens in the case of function + // calls or inline asm. Because of this, we also mark locals as + // conflicting when both of them are written to in the same + // statement. + if self.live.contains(q) || writes.contains(&q) { + CandidateFilter::Remove + } else { + CandidateFilter::Keep + } + }, self.at, ); } } - - /// Gets the write info for the `statement`. - fn get_statement_write_info(&mut self, statement: &StatementKind<'tcx>) { - self.write_info.writes.clear(); - match statement { - StatementKind::Assign(box (lhs, rhs)) => match rhs { - Rvalue::Use(op) => { - if !lhs.is_indirect() { - self.get_assign_use_write_info(*lhs, op); - return; - } - } - _ => (), - }, - _ => (), - } - - self.write_info.for_statement(statement); - } - - fn get_assign_use_write_info(&mut self, lhs: Place<'tcx>, rhs: &Operand<'tcx>) { - // We register the writes for the operand unconditionally - self.write_info.add_operand(rhs); - // However, we cannot do the same thing for the `lhs` as that would always block the - // optimization. Instead, we consider removing candidates manually. - let Some(rhs) = rhs.place() else { - self.write_info.add_place(lhs); - return; - }; - // Find out which candidate pair we should skip, if any - let Some((src, dest)) = places_to_candidate_pair(lhs, rhs, self.body) else { - self.write_info.add_place(lhs); - return; - }; - self.candidates.remove_candidates_if( - lhs.local, - |other| { - // Check if this is the candidate pair that should not be removed - if (lhs.local == src && other == dest) || (lhs.local == dest && other == src) { - return false; - } - // Otherwise, do the "standard" thing - self.live.contains(other) - }, - self.at, - ) - } } /// Describes where a statement/terminator writes to #[derive(Default, Debug)] struct WriteInfo { writes: Vec, + /// If this pair of locals is a candidate pair, completely skip processing it during this + /// statement. All other candidates are unaffected. + skip_pair: Option<(Local, Local)>, } impl WriteInfo { - fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>) { + fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>, body: &Body<'tcx>) { + self.reset(); match statement { StatementKind::Assign(box (lhs, rhs)) => { self.add_place(*lhs); match rhs { - Rvalue::Use(op) | Rvalue::Repeat(op, _) => { + Rvalue::Use(op) => { + self.add_operand(op); + self.consider_skipping_for_assign_use(*lhs, op, body); + } + Rvalue::Repeat(op, _) => { self.add_operand(op); } Rvalue::Cast(_, op, _) @@ -586,8 +580,22 @@ impl WriteInfo { } } + fn consider_skipping_for_assign_use<'tcx>( + &mut self, + lhs: Place<'tcx>, + rhs: &Operand<'tcx>, + body: &Body<'tcx>, + ) { + let Some(rhs) = rhs.place() else { + return + }; + if let Some(pair) = places_to_candidate_pair(lhs, rhs, body) { + self.skip_pair = Some(pair); + } + } + fn for_terminator<'tcx>(&mut self, terminator: &TerminatorKind<'tcx>) { - self.writes.clear(); + self.reset(); match terminator { TerminatorKind::SwitchInt { discr: op, .. } | TerminatorKind::Assert { cond: op, .. } => { @@ -657,15 +665,16 @@ impl WriteInfo { Operand::Copy(_) | Operand::Constant(_) => (), } } + + fn reset(&mut self) { + self.writes.clear(); + self.skip_pair = None; + } } ///////////////////////////////////////////////////// // Candidate accumulation -fn is_constant<'tcx>(place: Place<'tcx>) -> bool { - place.projection.iter().all(|p| !matches!(p, ProjectionElem::Deref | ProjectionElem::Index(_))) -} - /// If the pair of places is being considered for merging, returns the candidate which would be /// merged in order to accomplish this. /// @@ -741,10 +750,6 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, '_, 'tcx> { Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), )) = &statement.kind { - if !is_constant(*lhs) || !is_constant(*rhs) { - return; - } - let Some((src, dest)) = places_to_candidate_pair(*lhs, *rhs, self.body) else { return; }; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 6de564a3a0692..3bafd3730bd79 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -875,18 +875,12 @@ pub struct PacRet { pub key: PAuthKey, } -#[derive(Clone, Copy, Hash, Debug, PartialEq)] +#[derive(Clone, Copy, Hash, Debug, PartialEq, Default)] pub struct BranchProtection { pub bti: bool, pub pac_ret: Option, } -impl Default for BranchProtection { - fn default() -> Self { - BranchProtection { bti: false, pac_ret: None } - } -} - pub const fn default_lib_output() -> CrateType { CrateType::Rlib } @@ -1875,7 +1869,7 @@ fn parse_opt_level( .into_iter() .flat_map(|(i, s)| { // NB: This can match a string without `=`. - if let Some("opt-level") = s.splitn(2, '=').next() { Some(i) } else { None } + if let Some("opt-level") = s.split('=').next() { Some(i) } else { None } }) .max(); if max_o > max_c { @@ -1912,7 +1906,7 @@ fn select_debuginfo( .into_iter() .flat_map(|(i, s)| { // NB: This can match a string without `=`. - if let Some("debuginfo") = s.splitn(2, '=').next() { Some(i) } else { None } + if let Some("debuginfo") = s.split('=').next() { Some(i) } else { None } }) .max(); if max_g > max_c { diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs index d3c2c5113bcde..26cd54210d0bb 100644 --- a/compiler/rustc_span/src/analyze_source_file.rs +++ b/compiler/rustc_span/src/analyze_source_file.rs @@ -175,7 +175,7 @@ cfg_if::cfg_if! { // There might still be a tail left to analyze let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset; if tail_start < src.len() { - analyze_source_file_generic(&src[tail_start as usize ..], + analyze_source_file_generic(&src[tail_start ..], src.len() - tail_start, output_offset + BytePos::from_usize(tail_start), lines, @@ -219,7 +219,7 @@ fn analyze_source_file_generic( while i < scan_len { let byte = unsafe { // We verified that i < scan_len <= src.len() - *src_bytes.get_unchecked(i as usize) + *src_bytes.get_unchecked(i) }; // How much to advance in order to get to the next UTF-8 char in the diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 335bfc3302f27..5525eb5331c27 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1381,7 +1381,7 @@ impl Encodable for SourceFile { 4 => { raw_diffs = Vec::with_capacity(bytes_per_diff * num_diffs); for diff in diff_iter { - raw_diffs.extend_from_slice(&(diff.0 as u32).to_le_bytes()); + raw_diffs.extend_from_slice(&(diff.0).to_le_bytes()); } } _ => unreachable!(), diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index a4e0f54d27670..fb3e4a6c083f8 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -941,7 +941,7 @@ impl SourceMap { /// Otherwise, the span reached to limit is returned. pub fn span_look_ahead(&self, span: Span, expect: Option<&str>, limit: Option) -> Span { let mut sp = span; - for _ in 0..limit.unwrap_or(100 as usize) { + for _ in 0..limit.unwrap_or(100_usize) { sp = self.next_point(sp); if let Ok(ref snippet) = self.span_to_snippet(sp) { if expect.map_or(false, |es| snippet == es) { diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index fc6a2edabb763..44644c4733e87 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -81,7 +81,7 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs { _ => os.into(), }; - let platform_version: StaticCow = match os.as_ref() { + let platform_version: StaticCow = match os { "ios" => ios_lld_platform_version(), "tvos" => tvos_lld_platform_version(), "watchos" => watchos_lld_platform_version(), diff --git a/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs index e3eb9bccd5ed7..34934379c7e84 100644 --- a/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs +++ b/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs @@ -5,12 +5,7 @@ pub fn target() -> Target { base.max_atomic_width = Some(64); base.add_pre_link_args( LinkerFlavor::Unix(Cc::No), - &[ - "-b64".into(), - "-bpT:0x100000000".into(), - "-bpD:0x110000000".into(), - "-bcdtors:all:0:s".into(), - ], + &["-b64", "-bpT:0x100000000", "-bpD:0x110000000", "-bcdtors:all:0:s"], ); Target { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 3d8dfe81748c2..9c954e731219e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1636,17 +1636,30 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { infer::LateBoundRegionConversionTime::HigherRankedType, bound_predicate.rebind(data), ); - let normalized_ty = ocx.normalize( - &obligation.cause, - obligation.param_env, - self.tcx.mk_projection(data.projection_ty.def_id, data.projection_ty.substs), - ); + let unnormalized_term = match data.term.unpack() { + ty::TermKind::Ty(_) => self + .tcx + .mk_projection(data.projection_ty.def_id, data.projection_ty.substs) + .into(), + ty::TermKind::Const(ct) => self + .tcx + .mk_const( + ty::UnevaluatedConst { + def: ty::WithOptConstParam::unknown(data.projection_ty.def_id), + substs: data.projection_ty.substs, + }, + ct.ty(), + ) + .into(), + }; + let normalized_term = + ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term); debug!(?obligation.cause, ?obligation.param_env); - debug!(?normalized_ty, data.ty = ?data.term); + debug!(?normalized_term, data.ty = ?data.term); - let is_normalized_ty_expected = !matches!( + let is_normalized_term_expected = !matches!( obligation.cause.code().peel_derives(), ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::BindingObligation(_, _) @@ -1655,7 +1668,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::ObjectCastObligation(..) | ObligationCauseCode::OpaqueType ); - let expected_ty = data.term.ty().unwrap_or_else(|| self.tcx.ty_error()); // constrain inference variables a bit more to nested obligations from normalize so // we can have more helpful errors. @@ -1664,11 +1676,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Err(new_err) = ocx.eq_exp( &obligation.cause, obligation.param_env, - is_normalized_ty_expected, - normalized_ty, - expected_ty, + is_normalized_term_expected, + normalized_term, + data.term, ) { - (Some((data, is_normalized_ty_expected, normalized_ty, expected_ty)), new_err) + (Some((data, is_normalized_term_expected, normalized_term, data.term)), new_err) } else { (None, error.err) } @@ -1677,12 +1689,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }; let msg = values - .and_then(|(predicate, _, normalized_ty, expected_ty)| { - self.maybe_detailed_projection_msg( - predicate, - normalized_ty.into(), - expected_ty.into(), - ) + .and_then(|(predicate, _, normalized_term, expected_term)| { + self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term) }) .unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate)); let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}"); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 9589342b3c73f..c761a4dbe4500 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -919,7 +919,7 @@ fn variant_info_for_generator<'tcx>( def_id: DefId, substs: ty::SubstsRef<'tcx>, ) -> (Vec, Option) { - let Variants::Multiple { tag, ref tag_encoding, .. } = layout.variants else { + let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else { return (vec![], None); }; @@ -975,12 +975,28 @@ fn variant_info_for_generator<'tcx>( if variant_size == Size::ZERO { variant_size = upvars_size; } - // We need to add the discriminant size back into min_size, since it is subtracted - // later during printing. - variant_size += match tag_encoding { - TagEncoding::Direct => tag.size(cx), - _ => Size::ZERO, - }; + + // This `if` deserves some explanation. + // + // The layout code has a choice of where to place the discriminant of this generator. + // If the discriminant of the generator is placed early in the layout (before the + // variant's own fields), then it'll implicitly be counted towards the size of the + // variant, since we use the maximum offset to calculate size. + // (side-note: I know this is a bit problematic given upvars placement, etc). + // + // This is important, since the layout printing code always subtracts this discriminant + // size from the variant size if the struct is "enum"-like, so failing to account for it + // will either lead to numerical underflow, or an underreported variant size... + // + // However, if the discriminant is placed past the end of the variant, then we need + // to factor in the size of the discriminant manually. This really should be refactored + // better, but this "works" for now. + if layout.fields.offset(tag_field) >= variant_size { + variant_size += match tag_encoding { + TagEncoding::Direct => tag.size(cx), + _ => Size::ZERO, + }; + } VariantInfo { name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(variant_idx))), diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index e9ffbca96280d..f30ae82d7cdd2 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -250,9 +250,9 @@ impl Clone for TyKind { match self { Bool => Bool, Char => Char, - Int(i) => Int(i.clone()), - Uint(u) => Uint(u.clone()), - Float(f) => Float(f.clone()), + Int(i) => Int(*i), + Uint(u) => Uint(*u), + Float(f) => Float(*f), Adt(d, s) => Adt(d.clone(), s.clone()), Foreign(d) => Foreign(d.clone()), Str => Str, @@ -262,7 +262,7 @@ impl Clone for TyKind { Ref(r, t, m) => Ref(r.clone(), t.clone(), m.clone()), FnDef(d, s) => FnDef(d.clone(), s.clone()), FnPtr(s) => FnPtr(s.clone()), - Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), repr.clone()), + Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), *repr), Closure(d, s) => Closure(d.clone(), s.clone()), Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()), GeneratorWitness(g) => GeneratorWitness(g.clone()), @@ -270,7 +270,7 @@ impl Clone for TyKind { Tuple(t) => Tuple(t.clone()), Alias(k, p) => Alias(*k, p.clone()), Param(p) => Param(p.clone()), - Bound(d, b) => Bound(d.clone(), b.clone()), + Bound(d, b) => Bound(*d, b.clone()), Placeholder(p) => Placeholder(p.clone()), Infer(t) => Infer(t.clone()), Error(e) => Error(e.clone()), @@ -936,7 +936,7 @@ impl Clone for RegionKind { fn clone(&self) -> Self { match self { ReEarlyBound(r) => ReEarlyBound(r.clone()), - ReLateBound(d, r) => ReLateBound(d.clone(), r.clone()), + ReLateBound(d, r) => ReLateBound(*d, r.clone()), ReFree(r) => ReFree(r.clone()), ReStatic => ReStatic, ReVar(r) => ReVar(r.clone()), diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index c485ac9ddb8c1..bc1e15b359371 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1396,7 +1396,6 @@ kbd { vertical-align: middle; border: solid 1px var(--border-color); border-radius: 3px; - cursor: default; color: var(--kbd--color); background-color: var(--kbd-background); box-shadow: inset 0 -1px 0 var(--kbd-box-shadow-color); @@ -1970,7 +1969,6 @@ in storage.js } .scraped-example .code-wrapper .src-line-numbers { - margin: 0; padding: 14px 0; } diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index eba845bf5a915..a4097c456135d 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -150,8 +150,6 @@ pre, .rustdoc.source .example-wrap { color: #c5c5c5; } -.content .item-info::before { color: #ccc; } - .sidebar h2 a, .sidebar h3 a { color: white; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index d945e956c533e..a11aba12e0ac7 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -85,8 +85,6 @@ --table-alt-row-background-color: #2A2A2A; } -.content .item-info::before { color: #ccc; } - body.source .example-wrap pre.rust a { background: #333; } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 58955a79316af..f697724468fb3 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -82,8 +82,6 @@ --table-alt-row-background-color: #F5F5F5; } -.content .item-info::before { color: #ccc; } - body.source .example-wrap pre.rust a { background: #eee; } diff --git a/src/test/rustdoc-gui/help-page.goml b/src/test/rustdoc-gui/help-page.goml index 799ba851c92f9..80203901ed3c4 100644 --- a/src/test/rustdoc-gui/help-page.goml +++ b/src/test/rustdoc-gui/help-page.goml @@ -27,7 +27,6 @@ define-function: ( "color": |color|, "background-color": |background|, "box-shadow": |box_shadow| + " 0px -1px 0px 0px inset", - "cursor": "default", }, ALL)), ], ) diff --git a/src/test/ui/argument-suggestions/display-is-suggestable.rs b/src/test/ui/argument-suggestions/display-is-suggestable.rs new file mode 100644 index 0000000000000..d765bc4f74d33 --- /dev/null +++ b/src/test/ui/argument-suggestions/display-is-suggestable.rs @@ -0,0 +1,8 @@ +use std::fmt::Display; + +fn foo(x: &(dyn Display + Send)) {} + +fn main() { + foo(); + //~^ ERROR this function takes 1 argument but 0 arguments were supplied +} diff --git a/src/test/ui/argument-suggestions/display-is-suggestable.stderr b/src/test/ui/argument-suggestions/display-is-suggestable.stderr new file mode 100644 index 0000000000000..edd72b53eb3b6 --- /dev/null +++ b/src/test/ui/argument-suggestions/display-is-suggestable.stderr @@ -0,0 +1,19 @@ +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/display-is-suggestable.rs:6:5 + | +LL | foo(); + | ^^^-- an argument of type `&dyn std::fmt::Display + Send` is missing + | +note: function defined here + --> $DIR/display-is-suggestable.rs:3:4 + | +LL | fn foo(x: &(dyn Display + Send)) {} + | ^^^ ------------------------ +help: provide the argument + | +LL | foo(/* &dyn std::fmt::Display + Send */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/associated-type-bounds/const-projection-err.gce.stderr b/src/test/ui/associated-type-bounds/const-projection-err.gce.stderr new file mode 100644 index 0000000000000..0f1ec9ad0522f --- /dev/null +++ b/src/test/ui/associated-type-bounds/const-projection-err.gce.stderr @@ -0,0 +1,24 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-projection-err.rs:4:26 + | +LL | #![cfg_attr(gce, feature(generic_const_exprs))] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0271]: type mismatch resolving `::A == 1` + --> $DIR/const-projection-err.rs:14:11 + | +LL | foo::(); + | ^ expected `0`, found `1` + | +note: required by a bound in `foo` + --> $DIR/const-projection-err.rs:11:28 + | +LL | fn foo>() {} + | ^^^^^ required by this bound in `foo` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-type-bounds/const-projection-err.rs b/src/test/ui/associated-type-bounds/const-projection-err.rs new file mode 100644 index 0000000000000..bead85630016b --- /dev/null +++ b/src/test/ui/associated-type-bounds/const-projection-err.rs @@ -0,0 +1,18 @@ +// revisions: stock gce + +#![feature(associated_const_equality)] +#![cfg_attr(gce, feature(generic_const_exprs))] +//[gce]~^ WARN the feature `generic_const_exprs` is incomplete + +trait TraitWAssocConst { + const A: usize; +} + +fn foo>() {} + +fn bar>() { + foo::(); + //~^ ERROR type mismatch resolving `::A == 1` +} + +fn main() {} diff --git a/src/test/ui/associated-type-bounds/const-projection-err.stock.stderr b/src/test/ui/associated-type-bounds/const-projection-err.stock.stderr new file mode 100644 index 0000000000000..bf0824259a5a7 --- /dev/null +++ b/src/test/ui/associated-type-bounds/const-projection-err.stock.stderr @@ -0,0 +1,17 @@ +error[E0271]: type mismatch resolving `::A == 1` + --> $DIR/const-projection-err.rs:14:11 + | +LL | foo::(); + | ^ expected `1`, found `::A` + | + = note: expected constant `1` + found constant `::A` +note: required by a bound in `foo` + --> $DIR/const-projection-err.rs:11:28 + | +LL | fn foo>() {} + | ^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs index 61d7e2520eab7..1b1b3cffd58f3 100644 --- a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs +++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs @@ -1,4 +1,3 @@ -// check-pass // edition: 2021 #![feature(async_fn_in_trait)] @@ -13,11 +12,9 @@ trait MyTrait { } impl MyTrait for i32 { - // This will break once a PR that implements #102745 is merged fn foo(&self) -> Pin + '_>> { - Box::pin(async { - *self - }) + //~^ ERROR method `foo` should be async + Box::pin(async { *self }) } } diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr new file mode 100644 index 0000000000000..60fa534a64f02 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -0,0 +1,11 @@ +error: method `foo` should be async because the method from the trait is async + --> $DIR/async-example-desugared-boxed.rs:15:5 + | +LL | async fn foo(&self) -> i32; + | --------------------------- required because the trait method is async +... +LL | fn foo(&self) -> Pin + '_>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs b/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs new file mode 100644 index 0000000000000..81e1e59a36249 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs @@ -0,0 +1,37 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +use std::pin::Pin; +use std::task::Poll; + +trait MyTrait { + async fn foo(&self) -> i32; +} + +#[derive(Clone)] +struct MyFuture(i32); + +impl Future for MyFuture { + type Output = i32; + fn poll( + self: Pin<&mut Self>, + _: &mut std::task::Context<'_>, + ) -> Poll<::Output> { + Poll::Ready(self.0) + } +} + +impl MyTrait for i32 { + // FIXME: this should eventually require `#[refine]` to compile, because it also provides + // `Clone`. + fn foo(&self) -> impl Future + Clone { + MyFuture(*self) + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs b/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs new file mode 100644 index 0000000000000..71473e7455fd6 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs @@ -0,0 +1,29 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +use std::task::Poll; + +trait MyTrait { + async fn foo(&self) -> i32; +} + +struct MyFuture; +impl Future for MyFuture { + type Output = i32; + fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll { + Poll::Ready(0) + } +} + +impl MyTrait for u32 { + fn foo(&self) -> MyFuture { + //~^ ERROR method `foo` should be async + MyFuture + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr new file mode 100644 index 0000000000000..567a36a86d191 --- /dev/null +++ b/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -0,0 +1,11 @@ +error: method `foo` should be async because the method from the trait is async + --> $DIR/async-example-desugared-manual.rs:23:5 + | +LL | async fn foo(&self) -> i32; + | --------------------------- required because the trait method is async +... +LL | fn foo(&self) -> MyFuture { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/in-trait/async-example-desugared.rs b/src/test/ui/async-await/in-trait/async-example-desugared.rs index 1313c9edd861c..fb92ec786746f 100644 --- a/src/test/ui/async-await/in-trait/async-example-desugared.rs +++ b/src/test/ui/async-await/in-trait/async-example-desugared.rs @@ -12,11 +12,8 @@ trait MyTrait { } impl MyTrait for i32 { - // This will break once a PR that implements #102745 is merged fn foo(&self) -> impl Future + '_ { - async { - *self - } + async { *self } } } diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err.rs b/src/test/ui/async-await/in-trait/fn-not-async-err.rs index f94d32145a290..9598d53bce8b2 100644 --- a/src/test/ui/async-await/in-trait/fn-not-async-err.rs +++ b/src/test/ui/async-await/in-trait/fn-not-async-err.rs @@ -9,7 +9,7 @@ trait MyTrait { impl MyTrait for i32 { fn foo(&self) -> i32 { - //~^ ERROR: `i32` is not a future [E0277] + //~^ ERROR: method `foo` should be async *self } } diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err.stderr b/src/test/ui/async-await/in-trait/fn-not-async-err.stderr index 03321dc5b5af1..579801d0f3975 100644 --- a/src/test/ui/async-await/in-trait/fn-not-async-err.stderr +++ b/src/test/ui/async-await/in-trait/fn-not-async-err.stderr @@ -1,17 +1,11 @@ -error[E0277]: `i32` is not a future - --> $DIR/fn-not-async-err.rs:11:22 - | -LL | fn foo(&self) -> i32 { - | ^^^ `i32` is not a future - | - = help: the trait `Future` is not implemented for `i32` - = note: i32 must be a future or must implement `IntoFuture` to be awaited -note: required by a bound in `MyTrait::foo::{opaque#0}` - --> $DIR/fn-not-async-err.rs:7:28 +error: method `foo` should be async because the method from the trait is async + --> $DIR/fn-not-async-err.rs:11:5 | LL | async fn foo(&self) -> i32; - | ^^^ required by this bound in `MyTrait::foo::{opaque#0}` + | --------------------------- required because the trait method is async +... +LL | fn foo(&self) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err2.rs b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs index 594baa91ad8ba..2c4ed5535801e 100644 --- a/src/test/ui/async-await/in-trait/fn-not-async-err2.rs +++ b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs @@ -12,9 +12,7 @@ trait MyTrait { impl MyTrait for i32 { fn foo(&self) -> impl Future { //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562] - async { - *self - } + async { *self } } } diff --git a/src/test/ui/async-await/in-trait/issue-104678.rs b/src/test/ui/async-await/in-trait/issue-104678.rs new file mode 100644 index 0000000000000..e396df4e5d119 --- /dev/null +++ b/src/test/ui/async-await/in-trait/issue-104678.rs @@ -0,0 +1,31 @@ +// edition:2021 +// check-pass + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +pub trait Pool { + type Conn; + + async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future>( + &'a self, + callback: F, + ) -> (); +} + +pub struct PoolImpl; +pub struct ConnImpl; + +impl Pool for PoolImpl { + type Conn = ConnImpl; + + async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future>( + &'a self, + _callback: F, + ) -> () { + todo!() + } +} + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr index c1e235441d65d..d1d76916b2639 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr @@ -8,7 +8,7 @@ LL | pub struct Map { | doesn't satisfy `_: StreamExt` ... LL | let filter = map.filterx(|x: &_| true); - | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds + | ^^^^^^^ method cannot be called due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: `&'a mut &Map: Stream` @@ -29,7 +29,7 @@ LL | pub struct Filter { | doesn't satisfy `_: StreamExt` ... LL | let count = filter.countx(); - | ^^^^^^ method cannot be called on `Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>` due to unsatisfied trait bounds + | ^^^^^^ method cannot be called due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: `&'a mut &Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` diff --git a/src/test/ui/issues/issue-105330.stderr b/src/test/ui/issues/issue-105330.stderr index 92f2ccb6544b1..30c380152a5e6 100644 --- a/src/test/ui/issues/issue-105330.stderr +++ b/src/test/ui/issues/issue-105330.stderr @@ -55,8 +55,10 @@ error[E0271]: type mismatch resolving `::A == 32` --> $DIR/issue-105330.rs:12:11 | LL | foo::()(); - | ^^^^ types differ + | ^^^^ expected `32`, found `::A` | + = note: expected constant `32` + found constant `::A` note: required by a bound in `foo` --> $DIR/issue-105330.rs:11:28 | @@ -89,8 +91,10 @@ error[E0271]: type mismatch resolving `::A == 32` --> $DIR/issue-105330.rs:19:11 | LL | foo::(); - | ^^^^ types differ + | ^^^^ expected `32`, found `::A` | + = note: expected constant `32` + found constant `::A` note: required by a bound in `foo` --> $DIR/issue-105330.rs:11:28 | diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index b667ae0a78937..a32359c2b9f79 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -13,7 +13,7 @@ error[E0599]: the method `collect` exists for struct `Cloned $DIR/issue-31173.rs:12:10 | LL | .collect(); - | ^^^^^^^ method cannot be called on `Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>` due to unsatisfied trait bounds + | ^^^^^^^ method cannot be called due to unsatisfied trait bounds --> $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL | = note: doesn't satisfy `<_ as Iterator>::Item = &_` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index b91f75b97f84a..3151bc76891e4 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -17,7 +17,7 @@ error[E0599]: the method `count` exists for struct `Filter $DIR/issue-36053-2.rs:7:55 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | --------- ^^^^^ method cannot be called on `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>` due to unsatisfied trait bounds + | --------- ^^^^^ method cannot be called due to unsatisfied trait bounds | | | doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` | doesn't satisfy `_: FnMut<(&&str,)>` diff --git a/src/test/ui/print_type_sizes/async.rs b/src/test/ui/print_type_sizes/async.rs index 3491ad5afbc15..1598b0696913b 100644 --- a/src/test/ui/print_type_sizes/async.rs +++ b/src/test/ui/print_type_sizes/async.rs @@ -1,19 +1,11 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type lib // edition:2021 // build-pass // ignore-pass -#![feature(start)] - async fn wait() {} -async fn test(arg: [u8; 8192]) { +pub async fn test(arg: [u8; 8192]) { wait().await; drop(arg); } - -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - let _ = test([0; 8192]); - 0 -} diff --git a/src/test/ui/print_type_sizes/async.stdout b/src/test/ui/print_type_sizes/async.stdout index 94ad09ef296d3..6e47bb4930dc5 100644 --- a/src/test/ui/print_type_sizes/async.stdout +++ b/src/test/ui/print_type_sizes/async.stdout @@ -1,4 +1,4 @@ -print-type-size type: `[async fn body@$DIR/async.rs:10:32: 13:2]`: 16386 bytes, alignment: 1 bytes +print-type-size type: `[async fn body@$DIR/async.rs:8:36: 11:2]`: 16386 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Suspend0`: 16385 bytes print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes @@ -16,14 +16,14 @@ print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment print-type-size variant `MaybeUninit`: 8192 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 8192 bytes -print-type-size type: `[async fn body@$DIR/async.rs:8:17: 8:19]`: 1 bytes, alignment: 1 bytes +print-type-size type: `[async fn body@$DIR/async.rs:6:17: 6:19]`: 1 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes -print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes print-type-size field `.value`: 1 bytes -print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 1 bytes diff --git a/src/test/ui/print_type_sizes/generator.rs b/src/test/ui/print_type_sizes/generator.rs index a46db6121046b..d1cd36274ef3e 100644 --- a/src/test/ui/print_type_sizes/generator.rs +++ b/src/test/ui/print_type_sizes/generator.rs @@ -1,8 +1,8 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // ignore-pass -#![feature(start, generators, generator_trait)] +#![feature(generators, generator_trait)] use std::ops::Generator; @@ -13,8 +13,6 @@ fn generator(array: [u8; C]) -> impl Generator isize { +pub fn foo() { let _ = generator([0; 8192]); - 0 } diff --git a/src/test/ui/print_type_sizes/generator_discr_placement.rs b/src/test/ui/print_type_sizes/generator_discr_placement.rs new file mode 100644 index 0000000000000..1a85fe95bb6f7 --- /dev/null +++ b/src/test/ui/print_type_sizes/generator_discr_placement.rs @@ -0,0 +1,23 @@ +// compile-flags: -Z print-type-sizes --crate-type lib +// build-pass +// ignore-pass + +// Tests a generator that has its discriminant as the *final* field. + +// Avoid emitting panic handlers, like the rest of these tests... +#![feature(generators)] + +pub fn foo() { + let a = || { + { + let w: i32 = 4; + yield; + drop(w); + } + { + let z: i32 = 7; + yield; + drop(z); + } + }; +} diff --git a/src/test/ui/print_type_sizes/generator_discr_placement.stdout b/src/test/ui/print_type_sizes/generator_discr_placement.stdout new file mode 100644 index 0000000000000..7f8f4ccae7c14 --- /dev/null +++ b/src/test/ui/print_type_sizes/generator_discr_placement.stdout @@ -0,0 +1,11 @@ +print-type-size type: `[generator@$DIR/generator_discr_placement.rs:11:13: 11:15]`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Suspend0`: 7 bytes +print-type-size padding: 3 bytes +print-type-size field `.w`: 4 bytes, alignment: 4 bytes +print-type-size variant `Suspend1`: 7 bytes +print-type-size padding: 3 bytes +print-type-size field `.z`: 4 bytes, alignment: 4 bytes +print-type-size variant `Unresumed`: 0 bytes +print-type-size variant `Returned`: 0 bytes +print-type-size variant `Panicked`: 0 bytes diff --git a/src/test/ui/print_type_sizes/generics.rs b/src/test/ui/print_type_sizes/generics.rs index 3ef7b60db2cae..05097087d5a81 100644 --- a/src/test/ui/print_type_sizes/generics.rs +++ b/src/test/ui/print_type_sizes/generics.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. @@ -8,24 +8,6 @@ // monomorphized, in the MIR of the original function in which they // occur, to have their size reported. -#![feature(start)] - -// In an ad-hoc attempt to avoid the injection of unwinding code -// (which clutters the output of `-Z print-type-sizes` with types from -// `unwind::libunwind`): -// -// * I am not using Default to build values because that seems to -// cause the injection of unwinding code. (Instead I just make `fn new` -// methods.) -// -// * Pair derive Copy to ensure that we don't inject -// unwinding code into generic uses of Pair when T itself is also -// Copy. -// -// (I suspect this reflect some naivety within the rust compiler -// itself; it should be checking for drop glue, i.e., a destructor -// somewhere in the monomorphized types. It should not matter whether -// the type is Copy.) #[derive(Copy, Clone)] pub struct Pair { _car: T, @@ -61,11 +43,9 @@ pub fn f1(x: T) { Pair::new(FiftyBytes::new(), FiftyBytes::new()); } -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +pub fn start() { let _b: Pair = Pair::new(0, 0); let _s: Pair = Pair::new(SevenBytes::new(), SevenBytes::new()); let ref _z: ZeroSized = ZeroSized; f1::(SevenBytes::new()); - 0 } diff --git a/src/test/ui/print_type_sizes/multiple_types.rs b/src/test/ui/print_type_sizes/multiple_types.rs index f1ad27ec13137..9159038924719 100644 --- a/src/test/ui/print_type_sizes/multiple_types.rs +++ b/src/test/ui/print_type_sizes/multiple_types.rs @@ -1,11 +1,9 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // This file illustrates that when multiple structural types occur in // a function, every one of them is included in the output. -#![feature(start)] - pub struct SevenBytes([u8; 7]); pub struct FiftyBytes([u8; 50]); @@ -13,11 +11,3 @@ pub enum Enum { Small(SevenBytes), Large(FiftyBytes), } - -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - let _e: Enum; - let _f: FiftyBytes; - let _s: SevenBytes; - 0 -} diff --git a/src/test/ui/print_type_sizes/niche-filling.rs b/src/test/ui/print_type_sizes/niche-filling.rs index 0716cee21c662..5e620f248b65d 100644 --- a/src/test/ui/print_type_sizes/niche-filling.rs +++ b/src/test/ui/print_type_sizes/niche-filling.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. @@ -14,7 +14,6 @@ // aligned (while on most it is 8-byte aligned) and so the resulting // padding and overall computed sizes can be quite different. -#![feature(start)] #![feature(rustc_attrs)] #![allow(dead_code)] @@ -56,7 +55,7 @@ pub struct NestedNonZero { impl Default for NestedNonZero { fn default() -> Self { - NestedNonZero { pre: 0, val: NonZeroU32::new(1).unwrap(), post: 0 } + NestedNonZero { pre: 0, val: unsafe { NonZeroU32::new_unchecked(1) }, post: 0 } } } @@ -76,8 +75,7 @@ pub union Union2 { b: B, } -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +pub fn test() { let _x: MyOption = Default::default(); let _y: EmbeddedDiscr = Default::default(); let _z: MyOption = Default::default(); @@ -96,6 +94,4 @@ fn start(_: isize, _: *const *const u8) -> isize { // ...even when theoretically possible. let _j: MyOption> = Default::default(); let _k: MyOption> = Default::default(); - - 0 } diff --git a/src/test/ui/print_type_sizes/no_duplicates.rs b/src/test/ui/print_type_sizes/no_duplicates.rs index e45e4794a3526..2ec5d9e64bfbf 100644 --- a/src/test/ui/print_type_sizes/no_duplicates.rs +++ b/src/test/ui/print_type_sizes/no_duplicates.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. @@ -8,16 +8,12 @@ // (even if multiple functions), it is only printed once in the // print-type-sizes output. -#![feature(start)] - pub struct SevenBytes([u8; 7]); pub fn f1() { let _s: SevenBytes = SevenBytes([0; 7]); } -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +pub fn test() { let _s: SevenBytes = SevenBytes([0; 7]); - 0 } diff --git a/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs index 269cc3cc2825f..5ddfe4bf4dbb0 100644 --- a/src/test/ui/print_type_sizes/packed.rs +++ b/src/test/ui/print_type_sizes/packed.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. @@ -13,11 +13,10 @@ // padding and overall computed sizes can be quite different. #![allow(dead_code)] -#![feature(start)] #[derive(Default)] #[repr(packed)] -struct Packed1 { +pub struct Packed1 { a: u8, b: u8, g: i32, @@ -28,7 +27,7 @@ struct Packed1 { #[derive(Default)] #[repr(packed(2))] -struct Packed2 { +pub struct Packed2 { a: u8, b: u8, g: i32, @@ -40,7 +39,7 @@ struct Packed2 { #[derive(Default)] #[repr(packed(2))] #[repr(C)] -struct Packed2C { +pub struct Packed2C { a: u8, b: u8, g: i32, @@ -50,7 +49,7 @@ struct Packed2C { } #[derive(Default)] -struct Padded { +pub struct Padded { a: u8, b: u8, g: i32, @@ -58,12 +57,3 @@ struct Padded { h: i16, d: u8, } - -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - let _c: Packed1 = Default::default(); - let _d: Packed2 = Default::default(); - let _e: Packed2C = Default::default(); - let _f: Padded = Default::default(); - 0 -} diff --git a/src/test/ui/print_type_sizes/padding.rs b/src/test/ui/print_type_sizes/padding.rs index d1acad16d7e1d..f41c677dc6c08 100644 --- a/src/test/ui/print_type_sizes/padding.rs +++ b/src/test/ui/print_type_sizes/padding.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // This file illustrates how padding is handled: alignment @@ -9,7 +9,6 @@ // aligned (while on most it is 8-byte aligned) and so the resulting // padding and overall computed sizes can be quite different. -#![feature(start)] #![allow(dead_code)] struct S { @@ -27,8 +26,3 @@ enum E2 { A(i8, i32), B(S), } - -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - 0 -} diff --git a/src/test/ui/print_type_sizes/repr-align.rs b/src/test/ui/print_type_sizes/repr-align.rs index 07544935b2f82..0bd11ebc95843 100644 --- a/src/test/ui/print_type_sizes/repr-align.rs +++ b/src/test/ui/print_type_sizes/repr-align.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. @@ -11,7 +11,7 @@ // It avoids using u64/i64 because on some targets that is only 4-byte // aligned (while on most it is 8-byte aligned) and so the resulting // padding and overall computed sizes can be quite different. -#![feature(start)] + #![allow(dead_code)] #[repr(align(16))] @@ -24,15 +24,9 @@ enum E { } #[derive(Default)] -struct S { +pub struct S { a: i32, b: i32, c: A, d: i8, } - -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - let _s: S = Default::default(); - 0 -} diff --git a/src/test/ui/print_type_sizes/repr_int_c.rs b/src/test/ui/print_type_sizes/repr_int_c.rs index b8067c112eef1..6b103776a30d3 100644 --- a/src/test/ui/print_type_sizes/repr_int_c.rs +++ b/src/test/ui/print_type_sizes/repr_int_c.rs @@ -1,10 +1,9 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)` // variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug). -#![feature(start)] #![allow(dead_code)] #[repr(C, u8)] @@ -18,8 +17,3 @@ enum Repru8 { A(u16), B, } - -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - 0 -} diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs index 06a62db4ebb0f..86fab7b500af0 100644 --- a/src/test/ui/print_type_sizes/uninhabited.rs +++ b/src/test/ui/print_type_sizes/uninhabited.rs @@ -1,14 +1,12 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. // FIXME: consider using an attribute instead of side-effects. #![feature(never_type)] -#![feature(start)] -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +pub fn test() { let _x: Option = None; let _y: Result = Ok(42); let _z: Result = loop {}; diff --git a/src/test/ui/print_type_sizes/variants.rs b/src/test/ui/print_type_sizes/variants.rs index 6c8553cc23ded..5a3020520265d 100644 --- a/src/test/ui/print_type_sizes/variants.rs +++ b/src/test/ui/print_type_sizes/variants.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // This file illustrates two things: @@ -9,8 +9,6 @@ // 2. For an enum, the print-type-sizes output will also include the // size of each variant. -#![feature(start)] - pub struct SevenBytes([u8; 7]); pub struct FiftyBytes([u8; 50]); @@ -18,9 +16,3 @@ pub enum Enum { Small(SevenBytes), Large(FiftyBytes), } - -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - let _e: Enum; - 0 -} diff --git a/src/test/ui/print_type_sizes/zero-sized-fields.rs b/src/test/ui/print_type_sizes/zero-sized-fields.rs index e02a33109e56a..09415824d5df0 100644 --- a/src/test/ui/print_type_sizes/zero-sized-fields.rs +++ b/src/test/ui/print_type_sizes/zero-sized-fields.rs @@ -1,12 +1,10 @@ -// compile-flags: -Z print-type-sizes +// compile-flags: -Z print-type-sizes --crate-type=lib // build-pass // ignore-pass // At one point, zero-sized fields such as those in this file were causing // incorrect output from `-Z print-type-sizes`. -#![feature(start)] - struct S1 { x: u32, y: u32, @@ -28,8 +26,7 @@ struct S5 { tagz: TagZ, } -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +pub fn test() { let _s1: S1 = S1 { x: 0, y: 0, tag: () }; let _s5: S5<(), Empty> = S5 { @@ -43,5 +40,4 @@ fn start(_: isize, _: *const *const u8) -> isize { z: 4, tagz: Empty {}, }; - 0 }