diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index ab8ada1596c81..66ed49fe32676 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_middle::ty::{self, ToPolyTraitRef, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{Ident, Span}; pub use rustc_type_ir::elaborate::*; @@ -125,8 +125,8 @@ pub fn transitive_bounds_that_define_assoc_item<'tcx>( .iter_identity_copied() .map(|(clause, _)| clause.instantiate_supertrait(tcx, trait_ref)) .filter_map(|clause| clause.as_trait_clause()) - // FIXME: Negative supertraits are elaborated here lol - .map(|trait_pred| trait_pred.to_poly_trait_ref()), + .filter(|clause| clause.polarity() == ty::PredicatePolarity::Positive) + .map(|clause| clause.map_bound(|clause| clause.trait_ref)), ); return Some(trait_ref); diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index cd6b2d65bf184..65f51ae9d39c6 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -71,11 +71,7 @@ impl ConditionId { /// Enum that can hold a constant zero value, the ID of an physical coverage /// counter, or the ID of a coverage-counter expression. -/// -/// This was originally only used for expression operands (and named `Operand`), -/// but the zero/counter/expression distinction is also useful for representing -/// the value of code/gap mappings, and the true/false arms of branch mappings. -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum CovTerm { Zero, @@ -171,7 +167,7 @@ impl Op { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct Expression { pub lhs: CovTerm, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d2875fb37944a..ca70ae794c530 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -79,8 +79,7 @@ pub use self::predicate::{ PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate, - RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, TraitPredicate, TraitRef, - TypeOutlivesPredicate, + RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TraitRef, TypeOutlivesPredicate, }; pub use self::region::{ BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 32d6455e82557..584cac22ae8dd 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -476,16 +476,6 @@ impl<'tcx> Clause<'tcx> { } } -pub trait ToPolyTraitRef<'tcx> { - fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; -} - -impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { - fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { - self.map_bound_ref(|trait_pred| trait_pred.trait_ref) - } -} - impl<'tcx> UpcastFrom, PredicateKind<'tcx>> for Predicate<'tcx> { fn upcast_from(from: PredicateKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self { ty::Binder::dummy(from).upcast(tcx) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 1a9323329f61f..8d397f63cc7e0 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -1,10 +1,9 @@ use std::cmp::Ordering; -use std::fmt::{self, Debug}; use either::Either; use itertools::Itertools; use rustc_data_structures::captures::Captures; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::graph::DirectedGraph; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; @@ -20,134 +19,163 @@ mod iter_nodes; mod node_flow; mod union_find; -/// The coverage counter or counter expression associated with a particular -/// BCB node or BCB edge. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -enum BcbCounter { - Counter { id: CounterId }, - Expression { id: ExpressionId }, +/// Ensures that each BCB node needing a counter has one, by creating physical +/// counters or counter expressions for nodes as required. +pub(super) fn make_bcb_counters( + graph: &CoverageGraph, + bcb_needs_counter: &DenseBitSet, +) -> CoverageCounters { + // Create the derived graphs that are necessary for subsequent steps. + let balanced_graph = BalancedFlowGraph::for_graph(graph, |n| !graph[n].is_out_summable); + let merged_graph = MergedNodeFlowGraph::for_balanced_graph(&balanced_graph); + + // Use those graphs to determine which nodes get physical counters, and how + // to compute the execution counts of other nodes from those counters. + let nodes = make_node_counter_priority_list(graph, balanced_graph); + let node_counters = merged_graph.make_node_counters(&nodes); + + // Convert the counters into a form suitable for embedding into MIR. + transcribe_counters(&node_counters, bcb_needs_counter) } -impl BcbCounter { - fn as_term(&self) -> CovTerm { - match *self { - BcbCounter::Counter { id, .. } => CovTerm::Counter(id), - BcbCounter::Expression { id, .. } => CovTerm::Expression(id), - } - } +/// Arranges the nodes in `balanced_graph` into a list, such that earlier nodes +/// take priority in being given a counter expression instead of a physical counter. +fn make_node_counter_priority_list( + graph: &CoverageGraph, + balanced_graph: BalancedFlowGraph<&CoverageGraph>, +) -> Vec { + // A "reloop" node has exactly one out-edge, which jumps back to the top + // of an enclosing loop. Reloop nodes are typically visited more times + // than loop-exit nodes, so try to avoid giving them physical counters. + let is_reloop_node = IndexVec::from_fn_n( + |node| match graph.successors[node].as_slice() { + &[succ] => graph.dominates(succ, node), + _ => false, + }, + graph.num_nodes(), + ); + + let mut nodes = balanced_graph.iter_nodes().rev().collect::>(); + // The first node is the sink, which must not get a physical counter. + assert_eq!(nodes[0], balanced_graph.sink); + // Sort the real nodes, such that earlier (lesser) nodes take priority + // in being given a counter expression instead of a physical counter. + nodes[1..].sort_by(|&a, &b| { + // Start with a dummy `Equal` to make the actual tests line up nicely. + Ordering::Equal + // Prefer a physical counter for return/yield nodes. + .then_with(|| Ord::cmp(&graph[a].is_out_summable, &graph[b].is_out_summable)) + // Prefer an expression for reloop nodes (see definition above). + .then_with(|| Ord::cmp(&is_reloop_node[a], &is_reloop_node[b]).reverse()) + // Otherwise, prefer a physical counter for dominating nodes. + .then_with(|| graph.cmp_in_dominator_order(a, b).reverse()) + }); + nodes } -impl Debug for BcbCounter { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()), - Self::Expression { id } => write!(fmt, "Expression({:?})", id.index()), +// Converts node counters into a form suitable for embedding into MIR. +fn transcribe_counters( + old: &NodeCounters, + bcb_needs_counter: &DenseBitSet, +) -> CoverageCounters { + let mut new = CoverageCounters::with_num_bcbs(bcb_needs_counter.domain_size()); + + for bcb in bcb_needs_counter.iter() { + // Our counter-creation algorithm doesn't guarantee that a counter + // expression starts or ends with a positive term, so partition the + // counters into "positive" and "negative" lists for easier handling. + let (mut pos, mut neg): (Vec<_>, Vec<_>) = + old.counter_expr(bcb).iter().partition_map(|&CounterTerm { node, op }| match op { + Op::Add => Either::Left(node), + Op::Subtract => Either::Right(node), + }); + + if pos.is_empty() { + // If we somehow end up with no positive terms, fall back to + // creating a physical counter. There's no known way for this + // to happen, but we can avoid an ICE if it does. + debug_assert!(false, "{bcb:?} has no positive counter terms"); + pos = vec![bcb]; + neg = vec![]; } - } -} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -struct BcbExpression { - lhs: BcbCounter, - op: Op, - rhs: BcbCounter, -} + // These intermediate sorts are not strictly necessary, but were helpful + // in reducing churn when switching to the current counter-creation scheme. + // They also help to slightly decrease the overall size of the expression + // table, due to more subexpressions being shared. + pos.sort(); + neg.sort(); + + let mut new_counters_for_sites = |sites: Vec| { + sites.into_iter().map(|node| new.ensure_phys_counter(node)).collect::>() + }; + let mut pos = new_counters_for_sites(pos); + let mut neg = new_counters_for_sites(neg); + + // These sorts are also not strictly necessary; see above. + pos.sort(); + neg.sort(); + + let pos_counter = new.make_sum(&pos).expect("`pos` should not be empty"); + let new_counter = new.make_subtracted_sum(pos_counter, &neg); + new.set_node_counter(bcb, new_counter); + } -/// Enum representing either a node or an edge in the coverage graph. -/// -/// FIXME(#135481): This enum is no longer needed now that we only instrument -/// nodes and not edges. It can be removed in a subsequent PR. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub(super) enum Site { - Node { bcb: BasicCoverageBlock }, + new } /// Generates and stores coverage counter and coverage expression information -/// associated with nodes/edges in the BCB graph. +/// associated with nodes in the coverage graph. pub(super) struct CoverageCounters { /// List of places where a counter-increment statement should be injected /// into MIR, each with its corresponding counter ID. - counter_increment_sites: IndexVec, + phys_counter_for_node: FxIndexMap, + next_counter_id: CounterId, /// Coverage counters/expressions that are associated with individual BCBs. - node_counters: IndexVec>, + node_counters: IndexVec>, /// Table of expression data, associating each expression ID with its /// corresponding operator (+ or -) and its LHS/RHS operands. - expressions: IndexVec, + expressions: IndexVec, /// Remember expressions that have already been created (or simplified), /// so that we don't create unnecessary duplicates. - expressions_memo: FxHashMap, + expressions_memo: FxHashMap, } impl CoverageCounters { - /// Ensures that each BCB node needing a counter has one, by creating physical - /// counters or counter expressions for nodes and edges as required. - pub(super) fn make_bcb_counters( - graph: &CoverageGraph, - bcb_needs_counter: &DenseBitSet, - ) -> Self { - let balanced_graph = BalancedFlowGraph::for_graph(graph, |n| !graph[n].is_out_summable); - let merged_graph = MergedNodeFlowGraph::for_balanced_graph(&balanced_graph); - - // A "reloop" node has exactly one out-edge, which jumps back to the top - // of an enclosing loop. Reloop nodes are typically visited more times - // than loop-exit nodes, so try to avoid giving them physical counters. - let is_reloop_node = IndexVec::from_fn_n( - |node| match graph.successors[node].as_slice() { - &[succ] => graph.dominates(succ, node), - _ => false, - }, - graph.num_nodes(), - ); - - let mut nodes = balanced_graph.iter_nodes().rev().collect::>(); - // The first node is the sink, which must not get a physical counter. - assert_eq!(nodes[0], balanced_graph.sink); - // Sort the real nodes, such that earlier (lesser) nodes take priority - // in being given a counter expression instead of a physical counter. - nodes[1..].sort_by(|&a, &b| { - // Start with a dummy `Equal` to make the actual tests line up nicely. - Ordering::Equal - // Prefer a physical counter for return/yield nodes. - .then_with(|| Ord::cmp(&graph[a].is_out_summable, &graph[b].is_out_summable)) - // Prefer an expression for reloop nodes (see definition above). - .then_with(|| Ord::cmp(&is_reloop_node[a], &is_reloop_node[b]).reverse()) - // Otherwise, prefer a physical counter for dominating nodes. - .then_with(|| graph.cmp_in_dominator_order(a, b).reverse()) - }); - let node_counters = merged_graph.make_node_counters(&nodes); - - Transcriber::new(graph.num_nodes(), node_counters).transcribe_counters(bcb_needs_counter) - } - fn with_num_bcbs(num_bcbs: usize) -> Self { Self { - counter_increment_sites: IndexVec::new(), + phys_counter_for_node: FxIndexMap::default(), + next_counter_id: CounterId::ZERO, node_counters: IndexVec::from_elem_n(None, num_bcbs), expressions: IndexVec::new(), expressions_memo: FxHashMap::default(), } } - /// Creates a new physical counter for a BCB node or edge. - fn make_phys_counter(&mut self, site: Site) -> BcbCounter { - let id = self.counter_increment_sites.push(site); - BcbCounter::Counter { id } + /// Returns the physical counter for the given node, creating it if necessary. + fn ensure_phys_counter(&mut self, bcb: BasicCoverageBlock) -> CovTerm { + let id = *self.phys_counter_for_node.entry(bcb).or_insert_with(|| { + let id = self.next_counter_id; + self.next_counter_id = id + 1; + id + }); + CovTerm::Counter(id) } - fn make_expression(&mut self, lhs: BcbCounter, op: Op, rhs: BcbCounter) -> BcbCounter { - let new_expr = BcbExpression { lhs, op, rhs }; - *self.expressions_memo.entry(new_expr).or_insert_with(|| { + fn make_expression(&mut self, lhs: CovTerm, op: Op, rhs: CovTerm) -> CovTerm { + let new_expr = Expression { lhs, op, rhs }; + *self.expressions_memo.entry(new_expr.clone()).or_insert_with(|| { let id = self.expressions.push(new_expr); - BcbCounter::Expression { id } + CovTerm::Expression(id) }) } /// Creates a counter that is the sum of the given counters. /// /// Returns `None` if the given list of counters was empty. - fn make_sum(&mut self, counters: &[BcbCounter]) -> Option { + fn make_sum(&mut self, counters: &[CovTerm]) -> Option { counters .iter() .copied() @@ -155,16 +183,18 @@ impl CoverageCounters { } /// Creates a counter whose value is `lhs - SUM(rhs)`. - fn make_subtracted_sum(&mut self, lhs: BcbCounter, rhs: &[BcbCounter]) -> BcbCounter { + fn make_subtracted_sum(&mut self, lhs: CovTerm, rhs: &[CovTerm]) -> CovTerm { let Some(rhs_sum) = self.make_sum(rhs) else { return lhs }; self.make_expression(lhs, Op::Subtract, rhs_sum) } pub(super) fn num_counters(&self) -> usize { - self.counter_increment_sites.len() + let num_counters = self.phys_counter_for_node.len(); + assert_eq!(num_counters, self.next_counter_id.as_usize()); + num_counters } - fn set_node_counter(&mut self, bcb: BasicCoverageBlock, counter: BcbCounter) -> BcbCounter { + fn set_node_counter(&mut self, bcb: BasicCoverageBlock, counter: CovTerm) -> CovTerm { let existing = self.node_counters[bcb].replace(counter); assert!( existing.is_none(), @@ -174,16 +204,16 @@ impl CoverageCounters { } pub(super) fn term_for_bcb(&self, bcb: BasicCoverageBlock) -> Option { - self.node_counters[bcb].map(|counter| counter.as_term()) + self.node_counters[bcb] } - /// Returns an iterator over all the nodes/edges in the coverage graph that + /// Returns an iterator over all the nodes in the coverage graph that /// should have a counter-increment statement injected into MIR, along with /// each site's corresponding counter ID. pub(super) fn counter_increment_sites( &self, - ) -> impl Iterator + Captures<'_> { - self.counter_increment_sites.iter_enumerated().map(|(id, &site)| (id, site)) + ) -> impl Iterator + Captures<'_> { + self.phys_counter_for_node.iter().map(|(&site, &id)| (id, site)) } /// Returns an iterator over the subset of BCB nodes that have been associated @@ -193,93 +223,13 @@ impl CoverageCounters { ) -> impl Iterator + Captures<'_> { self.node_counters.iter_enumerated().filter_map(|(bcb, &counter)| match counter { // Yield the BCB along with its associated expression ID. - Some(BcbCounter::Expression { id }) => Some((bcb, id)), + Some(CovTerm::Expression(id)) => Some((bcb, id)), // This BCB is associated with a counter or nothing, so skip it. - Some(BcbCounter::Counter { .. }) | None => None, + Some(CovTerm::Counter { .. } | CovTerm::Zero) | None => None, }) } pub(super) fn into_expressions(self) -> IndexVec { - let old_len = self.expressions.len(); - let expressions = self - .expressions - .into_iter() - .map(|BcbExpression { lhs, op, rhs }| Expression { - lhs: lhs.as_term(), - op, - rhs: rhs.as_term(), - }) - .collect::>(); - - // Expression IDs are indexes into this vector, so make sure we didn't - // accidentally invalidate them by changing its length. - assert_eq!(old_len, expressions.len()); - expressions - } -} - -struct Transcriber { - old: NodeCounters, - new: CoverageCounters, - phys_counter_for_site: FxHashMap, -} - -impl Transcriber { - fn new(num_nodes: usize, old: NodeCounters) -> Self { - Self { - old, - new: CoverageCounters::with_num_bcbs(num_nodes), - phys_counter_for_site: FxHashMap::default(), - } - } - - fn transcribe_counters( - mut self, - bcb_needs_counter: &DenseBitSet, - ) -> CoverageCounters { - for bcb in bcb_needs_counter.iter() { - let site = Site::Node { bcb }; - let (mut pos, mut neg): (Vec<_>, Vec<_>) = - self.old.counter_expr(bcb).iter().partition_map( - |&CounterTerm { node, op }| match op { - Op::Add => Either::Left(node), - Op::Subtract => Either::Right(node), - }, - ); - - if pos.is_empty() { - // If we somehow end up with no positive terms, fall back to - // creating a physical counter. There's no known way for this - // to happen, but we can avoid an ICE if it does. - debug_assert!(false, "{site:?} has no positive counter terms"); - pos = vec![bcb]; - neg = vec![]; - } - - pos.sort(); - neg.sort(); - - let mut new_counters_for_sites = |sites: Vec| { - sites - .into_iter() - .map(|node| self.ensure_phys_counter(Site::Node { bcb: node })) - .collect::>() - }; - let mut pos = new_counters_for_sites(pos); - let mut neg = new_counters_for_sites(neg); - - pos.sort(); - neg.sort(); - - let pos_counter = self.new.make_sum(&pos).expect("`pos` should not be empty"); - let new_counter = self.new.make_subtracted_sum(pos_counter, &neg); - self.new.set_node_counter(bcb, new_counter); - } - - self.new - } - - fn ensure_phys_counter(&mut self, site: Site) -> BcbCounter { - *self.phys_counter_for_site.entry(site).or_insert_with(|| self.new.make_phys_counter(site)) + self.expressions } } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index b1b609595b74a..19568735df76e 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -21,7 +21,7 @@ use rustc_span::Span; use rustc_span::def_id::LocalDefId; use tracing::{debug, debug_span, trace}; -use crate::coverage::counters::{CoverageCounters, Site}; +use crate::coverage::counters::CoverageCounters; use crate::coverage::graph::CoverageGraph; use crate::coverage::mappings::ExtractedMappings; @@ -89,8 +89,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: return; } - let coverage_counters = - CoverageCounters::make_bcb_counters(&graph, &bcbs_with_counter_mappings); + let coverage_counters = counters::make_bcb_counters(&graph, &bcbs_with_counter_mappings); let mappings = create_mappings(&extracted_mappings, &coverage_counters); if mappings.is_empty() { @@ -239,14 +238,8 @@ fn inject_coverage_statements<'tcx>( coverage_counters: &CoverageCounters, ) { // Inject counter-increment statements into MIR. - for (id, site) in coverage_counters.counter_increment_sites() { - // Determine the block to inject a counter-increment statement into. - // For BCB nodes this is just their first block, but for edges we need - // to create a new block between the two BCBs, and inject into that. - let target_bb = match site { - Site::Node { bcb } => graph[bcb].leader_bb(), - }; - + for (id, bcb) in coverage_counters.counter_increment_sites() { + let target_bb = graph[bcb].leader_bb(); inject_statement(mir_body, CoverageKind::CounterIncrement { id }, target_bb); } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index dc26d4de57a7c..28829096bca73 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1,3 +1,5 @@ +use std::cmp::Reverse; + use rustc_ast::expand::StrippedCfgItem; use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; @@ -2243,13 +2245,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> Option<(Vec, Option)> { debug!("make_path_suggestion: span={:?} path={:?}", span, path); - match (path.get(0), path.get(1)) { + match path[..] { // `{{root}}::ident::...` on both editions. // On 2015 `{{root}}` is usually added implicitly. - (Some(fst), Some(snd)) + [fst, snd, ..] if fst.ident.name == kw::PathRoot && !snd.ident.is_path_segment_keyword() => {} // `ident::...` on 2018. - (Some(fst), _) + [fst, ..] if fst.ident.span.at_least_rust_2018() && !fst.ident.is_path_segment_keyword() => { // Insert a placeholder that's later replaced by `self`/`super`/etc. @@ -2357,7 +2359,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // 2) `std` suggestions before `core` suggestions. let mut extern_crate_names = self.extern_prelude.keys().map(|ident| ident.name).collect::>(); - extern_crate_names.sort_by(|a, b| b.as_str().partial_cmp(a.as_str()).unwrap()); + extern_crate_names.sort_by_key(|&name| Reverse(name)); for name in extern_crate_names.into_iter() { // Replace first ident with a crate name and check if that is valid. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c4aeaf478bd10..1a0292ebbde63 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3960,7 +3960,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { match res { Res::SelfCtor(_) // See #70549. | Res::Def( - DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::ConstParam, + DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::AssocConst | DefKind::ConstParam, _, ) if is_syntactic_ambiguity => { // Disambiguate in favor of a unit struct/variant or constant pattern. @@ -3969,7 +3969,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } Some(res) } - Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static { .. }, _) => { + Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::AssocConst | DefKind::Static { .. }, _) => { // This is unambiguously a fresh binding, either syntactically // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves // to something unusable as a pattern (e.g., constructor function), @@ -4005,7 +4005,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); None } - Res::Def(DefKind::Fn, _) | Res::Local(..) | Res::Err => { + Res::Def(DefKind::Fn | DefKind::AssocFn, _) | Res::Local(..) | Res::Err => { // These entities are explicitly allowed to be shadowed by fresh bindings. None } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index fc0de13aeab09..b4d294a70c071 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -172,14 +172,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let bound_predicate = predicate.kind(); let mut err = match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { - let trait_ref = bound_predicate.rebind(data.trait_ref); - debug!(?trait_ref); + let trait_pred = bound_predicate.rebind(data); + debug!(?trait_pred); if let Err(e) = predicate.error_reported() { return e; } - if let Err(guar) = self.tcx.ensure().coherent_trait(trait_ref.def_id()) { + if let Err(guar) = self.tcx.ensure().coherent_trait(trait_pred.def_id()) { // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. return guar; @@ -200,13 +200,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // avoid inundating the user with unnecessary errors, but we now // check upstream for type errors and don't add the obligations to // begin with in those cases. - if self.tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) { + if self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized) { match self.tainted_by_errors() { None => { let err = self.emit_inference_failure_err( obligation.cause.body_id, span, - trait_ref.self_ty().skip_binder().into(), + trait_pred.self_ty().skip_binder().into(), TypeAnnotationNeeded::E0282, false, ); @@ -251,10 +251,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut ambiguities = compute_applicable_impls_for_diagnostics( self.infcx, - &obligation.with(self.tcx, trait_ref), + &obligation.with(self.tcx, trait_pred), ); - let has_non_region_infer = - trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer()); + let has_non_region_infer = trait_pred + .skip_binder() + .trait_ref + .args + .types() + .any(|t| !t.is_ty_or_numeric_infer()); // It doesn't make sense to talk about applicable impls if there are more than a // handful of them. If there are a lot of them, but only a few of them have no type // params, we only show those, as they are more likely to be useful/intended. @@ -294,7 +298,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if impl_candidates.len() < 40 { self.report_similar_impl_candidates( impl_candidates.as_slice(), - trait_ref, + trait_pred, obligation.cause.body_id, &mut err, false, @@ -306,7 +310,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let ObligationCauseCode::WhereClause(def_id, _) | ObligationCauseCode::WhereClauseInExpr(def_id, ..) = *obligation.cause.code() { - self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); + self.suggest_fully_qualified_path(&mut err, def_id, span, trait_pred.def_id()); } if let Some(ty::GenericArgKind::Type(_)) = arg.map(|arg| arg.unpack()) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 6076c999086bf..c40ba33084569 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -23,9 +23,7 @@ use rustc_middle::ty::print::{ FmtPrinter, Print, PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _, PrintTraitRefExt as _, with_forced_trimmed_paths, }; -use rustc_middle::ty::{ - self, ToPolyTraitRef, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, -}; +use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast}; use rustc_middle::{bug, span_bug}; use rustc_span::{BytePos, DUMMY_SP, STDLIB_STABLE_CRATES, Span, Symbol, sym}; use tracing::{debug, instrument}; @@ -155,12 +153,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (leaf_trait_predicate, &obligation) }; - let main_trait_ref = main_trait_predicate.to_poly_trait_ref(); - let leaf_trait_ref = leaf_trait_predicate.to_poly_trait_ref(); - if let Some(guar) = self.emit_specialized_closure_kind_error( &obligation, - leaf_trait_ref, + leaf_trait_predicate, ) { return guar; } @@ -202,14 +197,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } = self.on_unimplemented_note(main_trait_predicate, main_obligation, &mut long_ty_file); let have_alt_message = message.is_some() || label.is_some(); - let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id()); + let is_try_conversion = self.is_try_conversion(span, main_trait_predicate.def_id()); let is_unsize = - self.tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Unsize); + self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Unsize); let (message, notes, append_const_msg) = if is_try_conversion { ( Some(format!( "`?` couldn't convert the error to `{}`", - main_trait_ref.skip_binder().self_ty(), + main_trait_predicate.skip_binder().self_ty(), )), vec![ "the question mark operation (`?`) implicitly performs a \ @@ -230,12 +225,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { post_message, ); - let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(main_trait_ref.def_id(), LangItem::TransmuteTrait) + let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::TransmuteTrait) { // Recompute the safe transmute reason and use that for the error reporting match self.get_safe_transmute_error_and_reason( obligation.clone(), - main_trait_ref, + main_trait_predicate, span, ) { GetSafeTransmuteErrorAndReason::Silent => { @@ -266,7 +261,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } let mut suggested = false; if is_try_conversion { - suggested = self.try_conversion_context(&obligation, main_trait_ref.skip_binder(), &mut err); + suggested = self.try_conversion_context(&obligation, main_trait_predicate, &mut err); } if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) { @@ -274,12 +269,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ret_span, format!( "expected `{}` because of this", - main_trait_ref.skip_binder().self_ty() + main_trait_predicate.skip_binder().self_ty() ), ); } - if tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Tuple) { + if tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Tuple) { self.add_tuple_trait_message( obligation.cause.code().peel_derives(), &mut err, @@ -319,7 +314,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // If it has a custom `#[rustc_on_unimplemented]` // error message, let's display it as the label! err.span_label(span, s); - if !matches!(leaf_trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) { + if !matches!(leaf_trait_predicate.skip_binder().self_ty().kind(), ty::Param(_)) { // When the self type is a type param We don't need to "the trait // `std::marker::Sized` is not implemented for `T`" as we will point // at the type param with a label to suggest constraining it. @@ -339,7 +334,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let ObligationCauseCode::Coercion { source, target } = *obligation.cause.code().peel_derives() { - if self.tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Sized) { + if self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Sized) { self.suggest_borrowing_for_object_cast( &mut err, root_obligation, @@ -368,7 +363,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.span_label(tcx.def_span(body), s); } - self.suggest_floating_point_literal(&obligation, &mut err, leaf_trait_ref); + self.suggest_floating_point_literal(&obligation, &mut err, leaf_trait_predicate); self.suggest_dereferencing_index(&obligation, &mut err, leaf_trait_predicate); suggested |= self.suggest_dereferences(&obligation, &mut err, leaf_trait_predicate); suggested |= self.suggest_fn_call(&obligation, &mut err, leaf_trait_predicate); @@ -376,7 +371,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { suggested = if let &[cand] = &impl_candidates[..] { let cand = cand.trait_ref; if let (ty::FnPtr(..), ty::FnDef(..)) = - (cand.self_ty().kind(), main_trait_ref.self_ty().skip_binder().kind()) + (cand.self_ty().kind(), main_trait_predicate.self_ty().skip_binder().kind()) { // Wrap method receivers and `&`-references in parens let suggestion = if self.tcx.sess.source_map().span_look_ahead(span, ".", Some(50)).is_some() { @@ -423,11 +418,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span, leaf_trait_predicate, ); - self.note_version_mismatch(&mut err, leaf_trait_ref); + self.note_version_mismatch(&mut err, leaf_trait_predicate); self.suggest_remove_await(&obligation, &mut err); self.suggest_derive(&obligation, &mut err, leaf_trait_predicate); - if tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Try) { + if tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Try) { self.suggest_await_before_try( &mut err, &obligation, @@ -455,9 +450,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } - let is_fn_trait = tcx.is_fn_trait(leaf_trait_ref.def_id()); + let is_fn_trait = tcx.is_fn_trait(leaf_trait_predicate.def_id()); let is_target_feature_fn = if let ty::FnDef(def_id, _) = - *leaf_trait_ref.skip_binder().self_ty().kind() + *leaf_trait_predicate.skip_binder().self_ty().kind() { !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() } else { @@ -509,7 +504,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } self.explain_hrtb_projection(&mut err, leaf_trait_predicate, obligation.param_env, &obligation.cause); - self.suggest_desugaring_async_fn_in_trait(&mut err, main_trait_ref); + self.suggest_desugaring_async_fn_in_trait(&mut err, main_trait_predicate); // Return early if the trait is Debug or Display and the invocation // originates within a standard library macro, because the output @@ -527,7 +522,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if in_std_macro && matches!( - self.tcx.get_diagnostic_name(leaf_trait_ref.def_id()), + self.tcx.get_diagnostic_name(leaf_trait_predicate.def_id()), Some(sym::Debug | sym::Display) ) { @@ -785,21 +780,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn emit_specialized_closure_kind_error( &self, obligation: &PredicateObligation<'tcx>, - mut trait_ref: ty::PolyTraitRef<'tcx>, + mut trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option { // If `AsyncFnKindHelper` is not implemented, that means that the closure kind // doesn't extend the goal kind. This is worth reporting, but we can only do so // if we actually know which closure this goal comes from, so look at the cause // to see if we can extract that information. - if self.tcx.is_lang_item(trait_ref.def_id(), LangItem::AsyncFnKindHelper) - && let Some(found_kind) = trait_ref.skip_binder().args.type_at(0).to_opt_closure_kind() + if self.tcx.is_lang_item(trait_pred.def_id(), LangItem::AsyncFnKindHelper) + && let Some(found_kind) = + trait_pred.skip_binder().trait_ref.args.type_at(0).to_opt_closure_kind() && let Some(expected_kind) = - trait_ref.skip_binder().args.type_at(1).to_opt_closure_kind() + trait_pred.skip_binder().trait_ref.args.type_at(1).to_opt_closure_kind() && !found_kind.extends(expected_kind) { if let Some((_, Some(parent))) = obligation.cause.code().parent_with_predicate() { // If we have a derived obligation, then the parent will be a `AsyncFn*` goal. - trait_ref = parent.to_poly_trait_ref(); + trait_pred = parent; } else if let &ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code() && let Some(typeck_results) = &self.typeck_results @@ -820,9 +816,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - let self_ty = trait_ref.self_ty().skip_binder(); + let self_ty = trait_pred.self_ty().skip_binder(); - if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()) { + if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()) { let (closure_def_id, found_args, by_ref_captures) = match *self_ty.kind() { ty::Closure(def_id, args) => { (def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), None) @@ -837,7 +833,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { _ => return None, }; - let expected_args = trait_ref.map_bound(|trait_ref| trait_ref.args.type_at(1)); + let expected_args = + trait_pred.map_bound(|trait_pred| trait_pred.trait_ref.args.type_at(1)); // Verify that the arguments are compatible. If the signature is // mismatched, then we have a totally different error to report. @@ -909,7 +906,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn try_conversion_context( &self, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::TraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, err: &mut Diag<'_>, ) -> bool { let span = obligation.cause.span; @@ -953,8 +950,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if !self.tcx.is_diagnostic_item(sym::FromResidual, y.def_id()) { return false; } - let self_ty = trait_ref.self_ty(); - let found_ty = trait_ref.args.get(1).and_then(|a| a.as_type()); + let self_ty = trait_pred.skip_binder().self_ty(); + let found_ty = trait_pred.skip_binder().trait_ref.args.get(1).and_then(|a| a.as_type()); let mut prev_ty = self.resolve_vars_if_possible( typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)), @@ -1223,18 +1220,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { goal: ty::TraitPredicate<'tcx>, assumption: ty::PolyTraitPredicate<'tcx>, ) -> bool { + // Fast path if goal.polarity != assumption.polarity() { return false; } - let trait_goal = goal.trait_ref; let trait_assumption = self.instantiate_binder_with_fresh_vars( DUMMY_SP, infer::BoundRegionConversionTime::HigherRankedType, - assumption.to_poly_trait_ref(), + assumption, ); - self.can_eq(ty::ParamEnv::empty(), trait_goal, trait_assumption) + self.can_eq(ty::ParamEnv::empty(), goal.trait_ref, trait_assumption.trait_ref) } fn can_match_projection( @@ -1682,7 +1679,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { pub(super) fn report_similar_impl_candidates( &self, impl_candidates: &[ImplCandidate<'tcx>], - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, body_def_id: LocalDefId, err: &mut Diag<'_>, other: bool, @@ -1727,7 +1724,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // We'll check for the case where the reason for the mismatch is that the trait comes from // one crate version and the type comes from another crate version, even though they both // are from the same crate. - let trait_def_id = trait_ref.def_id(); + let trait_def_id = trait_pred.def_id(); let trait_name = self.tcx.item_name(trait_def_id); let crate_name = self.tcx.crate_name(trait_def_id.krate); if let Some(other_trait_def_id) = self.tcx.all_traits().find(|def_id| { @@ -1739,7 +1736,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // different crate `DefId`. We highlight the traits. let found_type = - if let ty::Adt(def, _) = trait_ref.self_ty().skip_binder().peel_refs().kind() { + if let ty::Adt(def, _) = trait_pred.self_ty().skip_binder().peel_refs().kind() { Some(def.did()) } else { None @@ -1836,7 +1833,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if self.probe(|_| { let ocx = ObligationCtxt::new(self); - self.enter_forall(trait_ref, |obligation_trait_ref| { + self.enter_forall(trait_pred, |obligation_trait_ref| { let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id); let impl_trait_ref = ocx.normalize( &ObligationCause::dummy(), @@ -1864,7 +1861,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut terrs = vec![]; for (obligation_arg, impl_arg) in - std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args) + std::iter::zip(obligation_trait_ref.trait_ref.args, impl_trait_ref.args) { if (obligation_arg, impl_arg).references_error() { return false; @@ -1906,8 +1903,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } let traits = self.cmp_traits( - obligation_trait_ref.def_id, - &obligation_trait_ref.args[1..], + obligation_trait_ref.def_id(), + &obligation_trait_ref.trait_ref.args[1..], impl_trait_ref.def_id, &impl_trait_ref.args[1..], ); @@ -1991,7 +1988,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } if let &[cand] = &candidates[..] { let (desc, mention_castable) = - match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) { + match (cand.self_ty().kind(), trait_pred.self_ty().skip_binder().kind()) { (ty::FnPtr(..), ty::FnDef(..)) => { (" implemented for fn pointer `", ", cast using `as`") } @@ -2055,7 +2052,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .filter(|cand| !self.tcx.do_not_recommend_impl(cand.impl_def_id)) .collect::>(); - let def_id = trait_ref.def_id(); + let def_id = trait_pred.def_id(); if impl_candidates.is_empty() { if self.tcx.trait_is_auto(def_id) || self.tcx.lang_items().iter().any(|(_, id)| id == def_id) @@ -2132,11 +2129,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && !self.tcx.trait_is_auto(def_id) && !self.tcx.lang_items().iter().any(|(_, id)| id == def_id) { - let trait_ref = trait_pred.to_poly_trait_ref(); let impl_candidates = self.find_similar_impl_candidates(trait_pred); self.report_similar_impl_candidates( &impl_candidates, - trait_ref, + trait_pred, body_def_id, err, true, @@ -2173,12 +2169,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait /// with the same path as `trait_ref`, a help message about /// a probable version mismatch is added to `err` - fn note_version_mismatch(&self, err: &mut Diag<'_>, trait_ref: ty::PolyTraitRef<'tcx>) -> bool { + fn note_version_mismatch( + &self, + err: &mut Diag<'_>, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) -> bool { let get_trait_impls = |trait_def_id| { let mut trait_impls = vec![]; self.tcx.for_each_relevant_impl( trait_def_id, - trait_ref.skip_binder().self_ty(), + trait_pred.skip_binder().self_ty(), |impl_def_id| { trait_impls.push(impl_def_id); }, @@ -2186,11 +2186,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_impls }; - let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); + let required_trait_path = self.tcx.def_path_str(trait_pred.def_id()); let traits_with_same_path: UnordSet<_> = self .tcx .visible_traits() - .filter(|trait_def_id| *trait_def_id != trait_ref.def_id()) + .filter(|trait_def_id| *trait_def_id != trait_pred.def_id()) .map(|trait_def_id| (self.tcx.def_path_str(trait_def_id), trait_def_id)) .filter(|(p, _)| *p == required_trait_path) .collect(); @@ -2374,7 +2374,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn get_safe_transmute_error_and_reason( &self, obligation: PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, span: Span, ) -> GetSafeTransmuteErrorAndReason { use rustc_transmute::Answer; @@ -2386,19 +2386,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } // Erase regions because layout code doesn't particularly care about regions. - let trait_ref = - self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref)); + let trait_pred = + self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_pred)); let src_and_dst = rustc_transmute::Types { - dst: trait_ref.args.type_at(0), - src: trait_ref.args.type_at(1), + dst: trait_pred.trait_ref.args.type_at(0), + src: trait_pred.trait_ref.args.type_at(1), }; let ocx = ObligationCtxt::new(self); let Ok(assume) = ocx.structurally_normalize_const( &obligation.cause, obligation.param_env, - trait_ref.args.const_at(2), + trait_pred.trait_ref.args.const_at(2), ) else { self.dcx().span_delayed_bug( span, @@ -2417,8 +2417,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return GetSafeTransmuteErrorAndReason::Silent; }; - let dst = trait_ref.args.type_at(0); - let src = trait_ref.args.type_at(1); + let dst = trait_pred.trait_ref.args.type_at(0); + let src = trait_pred.trait_ref.args.type_at(1); let err_msg = format!("`{src}` cannot be safely transmuted into `{dst}`"); match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable( @@ -2566,12 +2566,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_predicate.skip_binder().polarity, ) { - self.add_help_message_for_fn_trait( - trait_predicate.to_poly_trait_ref(), - err, - implemented_kind, - params, - ); + self.add_help_message_for_fn_trait(trait_predicate, err, implemented_kind, params); } else if !trait_predicate.has_non_region_infer() && self.predicate_can_apply(obligation.param_env, trait_predicate) { @@ -2606,7 +2601,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let impl_candidates = self.find_similar_impl_candidates(trait_predicate); if !self.report_similar_impl_candidates( &impl_candidates, - trait_predicate.to_poly_trait_ref(), + trait_predicate, body_def_id, err, true, @@ -2623,7 +2618,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.suggest_convert_to_slice( err, obligation, - trait_predicate.to_poly_trait_ref(), + trait_predicate, impl_candidates.as_slice(), span, ); @@ -2634,7 +2629,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn add_help_message_for_fn_trait( &self, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, err: &mut Diag<'_>, implemented_kind: ty::ClosureKind, params: ty::Binder<'tcx, Ty<'tcx>>, @@ -2647,12 +2642,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // to implement. let selected_kind = self .tcx - .fn_trait_kind_from_def_id(trait_ref.def_id()) + .fn_trait_kind_from_def_id(trait_pred.def_id()) .expect("expected to map DefId to ClosureKind"); if !implemented_kind.extends(selected_kind) { err.note(format!( "`{}` implements `{}`, but it must implement `{}`, which is more general", - trait_ref.skip_binder().self_ty(), + trait_pred.skip_binder().self_ty(), implemented_kind, selected_kind )); @@ -2660,7 +2655,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Note any argument mismatches let given_ty = params.skip_binder(); - let expected_ty = trait_ref.skip_binder().args.type_at(1); + let expected_ty = trait_pred.skip_binder().trait_ref.args.type_at(1); if let ty::Tuple(given) = given_ty.kind() && let ty::Tuple(expected) = expected_ty.kind() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 2d248d00066e0..2d932e36470e2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -10,7 +10,7 @@ use rustc_hir::{AttrArgs, AttrKind, Attribute}; use rustc_macros::LintDiagnostic; use rustc_middle::bug; use rustc_middle::ty::print::PrintTraitRefExt as _; -use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, TyCtxt}; +use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, TyCtxt}; use rustc_parse_format::{ParseMode, Parser, Piece, Position}; use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES; use rustc_span::{Span, Symbol, kw, sym}; @@ -42,18 +42,18 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn impl_similar_to( &self, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, obligation: &PredicateObligation<'tcx>, ) -> Option<(DefId, GenericArgsRef<'tcx>)> { let tcx = self.tcx; let param_env = obligation.param_env; - self.enter_forall(trait_ref, |trait_ref| { - let trait_self_ty = trait_ref.self_ty(); + self.enter_forall(trait_pred, |trait_pred| { + let trait_self_ty = trait_pred.self_ty(); let mut self_match_impls = vec![]; let mut fuzzy_match_impls = vec![]; - self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| { + self.tcx.for_each_relevant_impl(trait_pred.def_id(), trait_self_ty, |def_id| { let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id); let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args); @@ -64,7 +64,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self_match_impls.push((def_id, impl_args)); if iter::zip( - trait_ref.args.types().skip(1), + trait_pred.trait_ref.args.types().skip(1), impl_trait_ref.args.types().skip(1), ) .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some()) @@ -117,7 +117,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } let (def_id, args) = self - .impl_similar_to(trait_pred.to_poly_trait_ref(), obligation) + .impl_similar_to(trait_pred, obligation) .unwrap_or_else(|| (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args)); let trait_pred = trait_pred.skip_binder(); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 9d85ca1dd4dd7..c2e73b732d314 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -32,9 +32,9 @@ use rustc_middle::ty::print::{ with_forced_trimmed_paths, with_no_trimmed_paths, }; use rustc_middle::ty::{ - self, AdtKind, GenericArgs, InferTy, IsSuggestable, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, - TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypeckResults, Upcast, - suggest_arbitrary_trait_bound, suggest_constraining_type_param, + self, AdtKind, GenericArgs, InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeVisitableExt, TypeckResults, Upcast, suggest_arbitrary_trait_bound, + suggest_constraining_type_param, }; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::LocalDefId; @@ -218,15 +218,15 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( (_, None) => predicate_constraint(hir_generics, trait_pred.upcast(tcx)), (None, Some((ident, []))) => ( ident.span.shrink_to_hi(), - format!(": {}", trait_pred.to_poly_trait_ref().print_trait_sugared()), + format!(": {}", trait_pred.print_modifiers_and_trait_path()), ), (_, Some((_, [.., bounds]))) => ( bounds.span().shrink_to_hi(), - format!(" + {}", trait_pred.to_poly_trait_ref().print_trait_sugared()), + format!(" + {}", trait_pred.print_modifiers_and_trait_path()), ), (Some(_), Some((_, []))) => ( hir_generics.span.shrink_to_hi(), - format!(": {}", trait_pred.to_poly_trait_ref().print_trait_sugared()), + format!(": {}", trait_pred.print_modifiers_and_trait_path()), ), }; @@ -3729,7 +3729,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut Diag<'_>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) { let rhs_span = match obligation.cause.code() { ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => { @@ -3737,8 +3737,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } _ => return, }; - if let ty::Float(_) = trait_ref.skip_binder().self_ty().kind() - && let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().args.type_at(1).kind() + if let ty::Float(_) = trait_pred.skip_binder().self_ty().kind() + && let ty::Infer(InferTy::IntVar(_)) = + trait_pred.skip_binder().trait_ref.args.type_at(1).kind() { err.span_suggestion_verbose( rhs_span.shrink_to_hi(), @@ -4448,7 +4449,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &self, err: &mut Diag<'_>, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, candidate_impls: &[ImplCandidate<'tcx>], span: Span, ) { @@ -4464,7 +4465,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // 1. `[T; _]` (array of T) // 2. `&[T; _]` (reference to array of T) // 3. `&mut [T; _]` (mutable reference to array of T) - let (element_ty, mut mutability) = match *trait_ref.skip_binder().self_ty().kind() { + let (element_ty, mut mutability) = match *trait_pred.skip_binder().self_ty().kind() { ty::Array(element_ty, _) => (element_ty, None), ty::Ref(_, pointee_ty, mutability) => match *pointee_ty.kind() { @@ -4620,14 +4621,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { pub(super) fn suggest_desugaring_async_fn_in_trait( &self, err: &mut Diag<'_>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) { // Don't suggest if RTN is active -- we should prefer a where-clause bound instead. if self.tcx.features().return_type_notation() { return; } - let trait_def_id = trait_ref.def_id(); + let trait_def_id = trait_pred.def_id(); // Only suggest specifying auto traits if !self.tcx.trait_is_auto(trait_def_id) { @@ -4635,7 +4636,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } // Look for an RPITIT - let ty::Alias(ty::Projection, alias_ty) = trait_ref.self_ty().skip_binder().kind() else { + let ty::Alias(ty::Projection, alias_ty) = trait_pred.self_ty().skip_binder().kind() else { return; }; let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) = diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 968dc631e50e5..b370f802052e7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -16,7 +16,7 @@ use rustc_infer::traits::{ Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError, }; use rustc_middle::ty::fast_reject::DeepRejectCtxt; -use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_type_ir::Interner; use tracing::{debug, instrument, trace}; @@ -186,10 +186,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } selcx.infcx.probe(|_| { + // We checked the polarity already match selcx.match_normalize_trait_ref( obligation, placeholder_trait_predicate.trait_ref, - bound.to_poly_trait_ref(), + bound.map_bound(|pred| pred.trait_ref), ) { Ok(None) => { candidates.vec.push(ProjectionCandidate(idx)); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 0ccb0fc0615c0..729ae3f2c2a26 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -16,7 +16,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk}; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; -use rustc_middle::ty::{self, GenericArgsRef, ToPolyTraitRef, Ty, TyCtxt, Upcast}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, Upcast}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; use rustc_type_ir::elaborate; @@ -458,8 +458,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ensure_sufficient_stack(|| { let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); - let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref); + assert_eq!(obligation.predicate.polarity(), ty::PredicatePolarity::Positive); + let trait_ref = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref; let trait_obligations = self.impl_or_trait_obligations( &cause, obligation.recursion_depth + 1, diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index a1f38b9ac147f..082b7431440ad 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -97,6 +97,11 @@ tidy: prepare: $(Q)$(BOOTSTRAP) build --stage 2 --dry-run +# Set of tests that represent around half of the time of the test suite. +# Used to split tests across multiple CI runners. +STAGE_2_TEST_SET1 := test --stage 2 --skip=compiler --skip=src +STAGE_2_TEST_SET2 := test --stage 2 --skip=tests --skip=coverage-map --skip=coverage-run --skip=library --skip=tidyselftest + ## MSVC native builders # this intentionally doesn't use `$(BOOTSTRAP)` so we can test the shebang on Windows @@ -105,6 +110,10 @@ ci-msvc-py: ci-msvc-ps1: $(Q)$(CFG_SRC_DIR)/x.ps1 test --stage 2 --skip tidy ci-msvc: ci-msvc-py ci-msvc-ps1 +ci-msvc-py-set1: + $(Q)$(CFG_SRC_DIR)/x.py $(STAGE_2_TEST_SET1) +ci-msvc-ps1-set2: + $(Q)$(CFG_SRC_DIR)/x.ps1 $(STAGE_2_TEST_SET2) ## MingW native builders @@ -112,9 +121,9 @@ ci-msvc: ci-msvc-py ci-msvc-ps1 # Used to split tests across multiple CI runners. # Test both x and bootstrap entrypoints. ci-mingw-x: - $(Q)$(CFG_SRC_DIR)/x test --stage 2 --skip=compiler --skip=src + $(Q)$(CFG_SRC_DIR)/x $(STAGE_2_TEST_SET1) ci-mingw-bootstrap: - $(Q)$(BOOTSTRAP) test --stage 2 --skip=tests --skip=coverage-map --skip=coverage-run --skip=library --skip=tidyselftest + $(Q)$(BOOTSTRAP) $(STAGE_2_TEST_SET2) ci-mingw: ci-mingw-x ci-mingw-bootstrap .PHONY: dist diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 2f52ff5a99a50..2b1de43c2f68c 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -305,8 +305,6 @@ For targets: `mips-unknown-linux-gnu` - Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} - Path and misc options > Use a mirror = ENABLE - Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc -- Path and misc options > Patches origin = Bundled, then local -- Path and misc options > Local patch directory = /tmp/patches - Target options > Target Architecture = mips - Target options > ABI = o32 - Target options > Endianness = Big endian @@ -327,8 +325,6 @@ For targets: `mipsel-unknown-linux-gnu` - Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} - Path and misc options > Use a mirror = ENABLE - Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc -- Path and misc options > Patches origin = Bundled, then local -- Path and misc options > Local patch directory = /tmp/patches - Target options > Target Architecture = mips - Target options > ABI = o32 - Target options > Endianness = Little endian @@ -349,8 +345,6 @@ For targets: `mips64-unknown-linux-gnuabi64` - Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} - Path and misc options > Use a mirror = ENABLE - Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc -- Path and misc options > Patches origin = Bundled, then local -- Path and misc options > Local patch directory = /tmp/patches - Target options > Target Architecture = mips - Target options > ABI = n64 - Target options > Endianness = Big endian @@ -370,8 +364,6 @@ For targets: `mips64el-unknown-linux-gnuabi64` - Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} - Path and misc options > Use a mirror = ENABLE - Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc -- Path and misc options > Patches origin = Bundled, then local -- Path and misc options > Local patch directory = /tmp/patches - Target options > Target Architecture = mips - Target options > ABI = n64 - Target options > Endianness = Little endian diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile index c08febf423adb..4a090dcdd5085 100644 --- a/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile @@ -11,7 +11,6 @@ RUN sh /scripts/rustbuild-setup.sh WORKDIR /tmp COPY scripts/crosstool-ng-build.sh /scripts/ -COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/ COPY host-x86_64/dist-mips-linux/mips-linux-gnu.defconfig /tmp/crosstool.defconfig RUN /scripts/crosstool-ng-build.sh diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.defconfig index 75743fe81416b..94db07922a226 100644 --- a/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.defconfig +++ b/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.defconfig @@ -2,8 +2,6 @@ CT_CONFIG_VERSION="4" CT_PREFIX_DIR="/x-tools/${CT_TARGET}" CT_USE_MIRROR=y CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" -CT_PATCH_BUNDLED_LOCAL=y -CT_LOCAL_PATCH_DIR="/tmp/patches" CT_ARCH_MIPS=y CT_ARCH_mips_o32=y CT_ARCH_ARCH="mips32r2" diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0001-MIPS-SPARC-fix-wrong-vfork-aliases-in-libpthread.so.patch b/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0001-MIPS-SPARC-fix-wrong-vfork-aliases-in-libpthread.so.patch deleted file mode 100644 index 393084df3249a..0000000000000 --- a/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0001-MIPS-SPARC-fix-wrong-vfork-aliases-in-libpthread.so.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 43c2948756bb6e144c7b871e827bba37d61ad3a3 Mon Sep 17 00:00:00 2001 -From: Aurelien Jarno -Date: Sat, 18 Jun 2016 19:11:23 +0200 -Subject: [PATCH 1/2] MIPS, SPARC: fix wrong vfork aliases in libpthread.so - -With recent binutils versions the GNU libc fails to build on at least -MISP and SPARC, with this kind of error: - - /home/aurel32/glibc/glibc-build/nptl/libpthread.so:(*IND*+0x0): multiple definition of `vfork@GLIBC_2.0' - /home/aurel32/glibc/glibc-build/nptl/libpthread.so::(.text+0xee50): first defined here - -It appears that on these architectures pt-vfork.S includes vfork.S -(through the alpha version of pt-vfork.S) and that the __vfork aliases -are not conditionalized on IS_IN (libc) like on other architectures. -Therefore the aliases are also wrongly included in libpthread.so. - -Fix this by properly conditionalizing the aliases like on other -architectures. - -Changelog: - * sysdeps/unix/sysv/linux/mips/vfork.S (__vfork): Conditionalize - hidden_def, weak_alias and strong_alias on [IS_IN (libc)]. - * sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: Likewise. - * sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: Likewise. ---- - sysdeps/unix/sysv/linux/mips/vfork.S | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/sysdeps/unix/sysv/linux/mips/vfork.S b/sysdeps/unix/sysv/linux/mips/vfork.S -index 8c6615143708..c0c0ce699159 100644 ---- a/sysdeps/unix/sysv/linux/mips/vfork.S -+++ b/sysdeps/unix/sysv/linux/mips/vfork.S -@@ -106,6 +106,8 @@ L(error): - #endif - END(__vfork) - -+#if IS_IN (libc) - libc_hidden_def(__vfork) - weak_alias (__vfork, vfork) - strong_alias (__vfork, __libc_vfork) -+#endif --- -2.37.3 - diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0002-MIPS-SPARC-more-fixes-to-the-vfork-aliases-in-libpth.patch b/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0002-MIPS-SPARC-more-fixes-to-the-vfork-aliases-in-libpth.patch deleted file mode 100644 index e28c7ae99f098..0000000000000 --- a/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0002-MIPS-SPARC-more-fixes-to-the-vfork-aliases-in-libpth.patch +++ /dev/null @@ -1,63 +0,0 @@ -From b87c1ec3fa398646f042a68f0ce0f7d09c1348c7 Mon Sep 17 00:00:00 2001 -From: Aurelien Jarno -Date: Tue, 21 Jun 2016 23:59:37 +0200 -Subject: [PATCH 2/2] MIPS, SPARC: more fixes to the vfork aliases in - libpthread.so - -Commit 43c29487 tried to fix the vfork aliases in libpthread.so on MIPS -and SPARC, but failed to do it correctly, introducing an ABI change. - -This patch does the remaining changes needed to align the MIPS and SPARC -vfork implementations with the other architectures. That way the the -alpha version of pt-vfork.S works correctly for MIPS and SPARC. The -changes for alpha were done in 82aab97c. - -Changelog: - * sysdeps/unix/sysv/linux/mips/vfork.S (__vfork): Rename into - __libc_vfork. - (__vfork) [IS_IN (libc)]: Remove alias. - (__libc_vfork) [IS_IN (libc)]: Define as an alias. - * sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: Likewise. - * sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: Likewise. ---- - sysdeps/unix/sysv/linux/mips/vfork.S | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/sysdeps/unix/sysv/linux/mips/vfork.S b/sysdeps/unix/sysv/linux/mips/vfork.S -index c0c0ce699159..1867c8626ebe 100644 ---- a/sysdeps/unix/sysv/linux/mips/vfork.S -+++ b/sysdeps/unix/sysv/linux/mips/vfork.S -@@ -31,13 +31,13 @@ - LOCALSZ= 1 - FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK - GPOFF= FRAMESZ-(1*SZREG) --NESTED(__vfork,FRAMESZ,sp) -+NESTED(__libc_vfork,FRAMESZ,sp) - #ifdef __PIC__ - SETUP_GP - #endif - PTR_SUBU sp, FRAMESZ - cfi_adjust_cfa_offset (FRAMESZ) -- SETUP_GP64_REG (a5, __vfork) -+ SETUP_GP64_REG (a5, __libc_vfork) - #ifdef __PIC__ - SAVE_GP (GPOFF) - #endif -@@ -104,10 +104,10 @@ L(error): - RESTORE_GP64_REG - j __syscall_error - #endif -- END(__vfork) -+ END(__libc_vfork) - - #if IS_IN (libc) --libc_hidden_def(__vfork) --weak_alias (__vfork, vfork) --strong_alias (__vfork, __libc_vfork) -+weak_alias (__libc_vfork, vfork) -+strong_alias (__libc_vfork, __vfork) -+libc_hidden_def (__vfork) - #endif --- -2.37.3 - diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile index 10f31075e2d55..18b0375f40080 100644 --- a/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile @@ -11,7 +11,6 @@ RUN sh /scripts/rustbuild-setup.sh WORKDIR /tmp COPY scripts/crosstool-ng-build.sh /scripts/ -COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/ COPY host-x86_64/dist-mips64-linux/mips64-linux-gnu.defconfig /tmp/crosstool.defconfig RUN /scripts/crosstool-ng-build.sh diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.defconfig index 4b8f7a5492033..f295a2fafc6b1 100644 --- a/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.defconfig +++ b/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.defconfig @@ -2,8 +2,6 @@ CT_CONFIG_VERSION="4" CT_PREFIX_DIR="/x-tools/${CT_TARGET}" CT_USE_MIRROR=y CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" -CT_PATCH_BUNDLED_LOCAL=y -CT_LOCAL_PATCH_DIR="/tmp/patches" CT_ARCH_MIPS=y CT_ARCH_mips_n64=y CT_ARCH_64=y diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile index 5ab4a53de8a88..87407203880b4 100644 --- a/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile @@ -11,7 +11,6 @@ RUN sh /scripts/rustbuild-setup.sh WORKDIR /tmp COPY scripts/crosstool-ng-build.sh /scripts/ -COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/ COPY host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.defconfig /tmp/crosstool.defconfig RUN /scripts/crosstool-ng-build.sh diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.defconfig index 9c8eb5007b79b..47d6246356526 100644 --- a/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.defconfig +++ b/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.defconfig @@ -2,8 +2,6 @@ CT_CONFIG_VERSION="4" CT_PREFIX_DIR="/x-tools/${CT_TARGET}" CT_USE_MIRROR=y CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" -CT_PATCH_BUNDLED_LOCAL=y -CT_LOCAL_PATCH_DIR="/tmp/patches" CT_ARCH_MIPS=y CT_ARCH_mips_n64=y CT_ARCH_LE=y diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile index 0bbaf00339d0a..553f6ea86b72d 100644 --- a/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile @@ -11,7 +11,6 @@ RUN sh /scripts/rustbuild-setup.sh WORKDIR /tmp COPY scripts/crosstool-ng-build.sh /scripts/ -COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/ COPY host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.defconfig /tmp/crosstool.defconfig RUN /scripts/crosstool-ng-build.sh diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.defconfig index a9dae121e536a..5daa83ebc02a7 100644 --- a/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.defconfig +++ b/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.defconfig @@ -2,8 +2,6 @@ CT_CONFIG_VERSION="4" CT_PREFIX_DIR="/x-tools/${CT_TARGET}" CT_USE_MIRROR=y CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" -CT_PATCH_BUNDLED_LOCAL=y -CT_LOCAL_PATCH_DIR="/tmp/patches" CT_ARCH_MIPS=y CT_ARCH_mips_o32=y CT_ARCH_LE=y diff --git a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile index f52e306974cce..9ca8cc740a5c7 100644 --- a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile @@ -1,4 +1,6 @@ -FROM ubuntu:22.04 +# We use the ghcr base image because ghcr doesn't have a rate limit +# and the mingw-check-tidy job doesn't cache docker images in CI. +FROM ghcr.io/rust-lang/ubuntu:22.04 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 1ab70e4e0aaba..799ea3e9ad2df 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -448,11 +448,18 @@ auto: SCRIPT: make ci-msvc <<: *job-windows-8c - - name: i686-msvc + # i686-msvc is split into two jobs to run tests in parallel. + - name: i686-msvc-1 env: RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-msvc - <<: *job-windows-8c + SCRIPT: make ci-msvc-py-set1 + <<: *job-windows + + - name: i686-msvc-2 + env: + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-msvc-ps1-set2 + <<: *job-windows # x86_64-msvc-ext is split into multiple jobs to run tests in parallel. - name: x86_64-msvc-ext1 diff --git a/tests/ui/resolve/resolve-issue-135614-assoc-const.import_trait_associated_functions.stderr b/tests/ui/resolve/resolve-issue-135614-assoc-const.import_trait_associated_functions.stderr new file mode 100644 index 0000000000000..b41fa1818e25a --- /dev/null +++ b/tests/ui/resolve/resolve-issue-135614-assoc-const.import_trait_associated_functions.stderr @@ -0,0 +1,19 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/resolve-issue-135614-assoc-const.rs:21:9 + | +LL | let DEFAULT: u32 = 0; + | ^^^^^^^ pattern `1_u32..=u32::MAX` not covered +LL | const DEFAULT: u32 = 0; + | ------------------ missing patterns are not covered because `DEFAULT` is interpreted as a constant pattern, not a new variable + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html + = note: the matched value is of type `u32` +help: introduce a variable instead + | +LL | let DEFAULT_var: u32 = 0; + | ~~~~~~~~~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/resolve/resolve-issue-135614-assoc-const.normal.stderr b/tests/ui/resolve/resolve-issue-135614-assoc-const.normal.stderr new file mode 100644 index 0000000000000..908f5bdd89749 --- /dev/null +++ b/tests/ui/resolve/resolve-issue-135614-assoc-const.normal.stderr @@ -0,0 +1,30 @@ +error[E0658]: `use` associated items of traits is unstable + --> $DIR/resolve-issue-135614-assoc-const.rs:6:5 + | +LL | use MyDefault::DEFAULT; + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #134691 for more information + = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0005]: refutable pattern in local binding + --> $DIR/resolve-issue-135614-assoc-const.rs:21:9 + | +LL | let DEFAULT: u32 = 0; + | ^^^^^^^ pattern `1_u32..=u32::MAX` not covered +LL | const DEFAULT: u32 = 0; + | ------------------ missing patterns are not covered because `DEFAULT` is interpreted as a constant pattern, not a new variable + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html + = note: the matched value is of type `u32` +help: introduce a variable instead + | +LL | let DEFAULT_var: u32 = 0; + | ~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0005, E0658. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/resolve/resolve-issue-135614-assoc-const.rs b/tests/ui/resolve/resolve-issue-135614-assoc-const.rs new file mode 100644 index 0000000000000..5a592922cd461 --- /dev/null +++ b/tests/ui/resolve/resolve-issue-135614-assoc-const.rs @@ -0,0 +1,30 @@ +//@ revisions: normal import_trait_associated_functions +#![cfg_attr(import_trait_associated_functions, feature(import_trait_associated_functions))] + +// Makes sure that imported constant can be used in pattern bindings. + +use MyDefault::DEFAULT; //[normal]~ ERROR `use` associated items of traits is unstable + +trait MyDefault { + const DEFAULT: Self; +} + +impl MyDefault for u32 { + const DEFAULT: u32 = 0; +} + +impl MyDefault for () { + const DEFAULT: () = (); +} + +fn foo(x: u32) -> u32 { + let DEFAULT: u32 = 0; //~ ERROR refutable pattern in local binding + const DEFAULT: u32 = 0; + if let DEFAULT = x { DEFAULT } else { 1 } +} + +fn bar() { + let DEFAULT = (); +} + +fn main() {} diff --git a/tests/ui/resolve/resolve-issue-135614.normal.stderr b/tests/ui/resolve/resolve-issue-135614.normal.stderr new file mode 100644 index 0000000000000..a9adeb0848e6f --- /dev/null +++ b/tests/ui/resolve/resolve-issue-135614.normal.stderr @@ -0,0 +1,13 @@ +error[E0658]: `use` associated items of traits is unstable + --> $DIR/resolve-issue-135614.rs:7:5 + | +LL | use A::b; + | ^^^^ + | + = note: see issue #134691 for more information + = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/resolve/resolve-issue-135614.rs b/tests/ui/resolve/resolve-issue-135614.rs new file mode 100644 index 0000000000000..fec9499365bcb --- /dev/null +++ b/tests/ui/resolve/resolve-issue-135614.rs @@ -0,0 +1,15 @@ +//@ revisions: normal import_trait_associated_functions +//@[import_trait_associated_functions] check-pass +#![cfg_attr(import_trait_associated_functions, feature(import_trait_associated_functions))] + +// Makes sure that imported associated functions are shadowed by the local declarations. + +use A::b; //[normal]~ ERROR `use` associated items of traits is unstable + +trait A { + fn b() {} +} + +fn main() { + let b: (); +}