diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 92b9adf1db751..fbae496458813 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -8,7 +8,6 @@ use rustc_lexer::unescape::{ }; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; -use std::ops::Range; use std::{ascii, fmt, str}; // Escapes a string, represented as a symbol. Reuses the original symbol, @@ -39,7 +38,6 @@ pub enum LitError { InvalidFloatSuffix, NonDecimalFloat(u32), IntTooLarge(u32), - NulInCStr(Range), } impl LitKind { @@ -156,10 +154,7 @@ impl LitKind { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_c_string(s, Mode::CStr, &mut |span, c| match c { - Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => { - error = Err(LitError::NulInCStr(span)); - } + unescape_c_string(s, Mode::CStr, &mut |_span, c| match c { Ok(CStrUnit::Byte(b)) => buf.push(b), Ok(CStrUnit::Char(c)) => { buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) @@ -179,10 +174,7 @@ impl LitKind { // can convert the symbol directly to a `Lrc` on success. let s = symbol.as_str(); let mut error = Ok(()); - unescape_c_string(s, Mode::RawCStr, &mut |span, c| match c { - Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => { - error = Err(LitError::NulInCStr(span)); - } + unescape_c_string(s, Mode::RawCStr, &mut |_, c| match c { Ok(_) => {} Err(err) => { if err.is_fatal() { diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index d11198d7fd4e7..d5a39cd840587 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -754,16 +754,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { get_future_output(obligation.predicate, obligation.cause.span) })? } + ty::Alias(ty::Projection, _) => { + return Some(Ty::new_error_with_message( + self.tcx, + closure_span, + "this projection should have been projected to an opaque type", + )); + } ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self .tcx .explicit_item_bounds(def_id) .iter_instantiated_copied(self.tcx, args) .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, ty::Error(_) => return Some(ret_ty), - _ => span_bug!( - closure_span, - "async fn coroutine return type not an inference variable: {ret_ty}" - ), + _ => { + span_bug!(closure_span, "invalid async fn coroutine return type: {ret_ty:?}") + } }; let output_ty = self.normalize(closure_span, output_ty); diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index e85c940f1b55c..03c8e08aa01ac 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -13,7 +13,9 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource}; use rustc_middle::hir::nested_filter; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use rustc_middle::infer::unify_key::{ + ConstVariableOrigin, ConstVariableOriginKind, ConstVariableValue, +}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; use rustc_middle::ty::{self, InferConst}; @@ -178,17 +180,23 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte } }; printer.ty_infer_name_resolver = Some(Box::new(ty_getter)); - let const_getter = move |ct_vid| { - if infcx.probe_const_var(ct_vid).is_ok() { + let const_getter = move |ct_vid| match infcx + .inner + .borrow_mut() + .const_unification_table() + .probe_value(ct_vid) + { + ConstVariableValue::Known { value: _ } => { warn!("resolved const var in error message"); - } - if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = - infcx.inner.borrow_mut().const_unification_table().probe_value(ct_vid).origin.kind - { - return Some(name); - } else { None } + ConstVariableValue::Unknown { origin, universe: _ } => { + if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = origin.kind { + return Some(name); + } else { + None + } + } }; printer.const_infer_name_resolver = Some(Box::new(const_getter)); printer @@ -303,7 +311,12 @@ impl<'tcx> InferCtxt<'tcx> { GenericArgKind::Const(ct) => { if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() { let origin = - self.inner.borrow_mut().const_unification_table().probe_value(vid).origin; + match self.inner.borrow_mut().const_unification_table().probe_value(vid) { + ConstVariableValue::Known { value } => { + bug!("resolved infer var: {vid:?} {value}") + } + ConstVariableValue::Unknown { origin, universe: _ } => origin, + }; if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = origin.kind { diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index c7cab048db1ba..d256994d8d1fd 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -146,14 +146,8 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { ty::ConstKind::Infer(ty::InferConst::Var(v)) => { - let opt_ct = self - .infcx - .inner - .borrow_mut() - .const_unification_table() - .probe_value(v) - .val - .known(); + let opt_ct = + self.infcx.inner.borrow_mut().const_unification_table().probe_value(v).known(); self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty()) } ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => { diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs index 8ca97ae1b8e5d..99033922bdf76 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/fudge.rs @@ -1,4 +1,4 @@ -use rustc_middle::infer::unify_key::ConstVidKey; +use rustc_middle::infer::unify_key::{ConstVariableOriginKind, ConstVariableValue, ConstVidKey}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid}; @@ -28,10 +28,17 @@ fn const_vars_since_snapshot<'tcx>( snapshot_var_len: usize, ) -> (Range, Vec) { let range = vars_since_snapshot(table, snapshot_var_len); + ( range.start.vid..range.end.vid, (range.start.index()..range.end.index()) - .map(|index| table.probe_value(ConstVid::from_u32(index)).origin) + .map(|index| match table.probe_value(ConstVid::from_u32(index)) { + ConstVariableValue::Known { value: _ } => ConstVariableOrigin { + kind: ConstVariableOriginKind::MiscVariable, + span: rustc_span::DUMMY_SP, + }, + ConstVariableValue::Unknown { origin, universe: _ } => origin, + }) .collect(), ) } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e164041c5991e..002aad19c4981 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -23,8 +23,8 @@ use rustc_data_structures::unify as ut; use rustc_errors::{DiagCtxt, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVarValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; +use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::{select, DefiningAnchor}; @@ -1086,7 +1086,7 @@ impl<'tcx> InferCtxt<'tcx> { .inner .borrow_mut() .const_unification_table() - .new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } }) + .new_key(ConstVariableValue::Unknown { origin, universe }) .vid; ty::Const::new_var(self.tcx, vid, ty) } @@ -1095,10 +1095,7 @@ impl<'tcx> InferCtxt<'tcx> { self.inner .borrow_mut() .const_unification_table() - .new_key(ConstVarValue { - origin, - val: ConstVariableValue::Unknown { universe: self.universe() }, - }) + .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() }) .vid } @@ -1217,10 +1214,7 @@ impl<'tcx> InferCtxt<'tcx> { .inner .borrow_mut() .const_unification_table() - .new_key(ConstVarValue { - origin, - val: ConstVariableValue::Unknown { universe: self.universe() }, - }) + .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() }) .vid; ty::Const::new_var( self.tcx, @@ -1410,9 +1404,9 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn probe_const_var(&self, vid: ty::ConstVid) -> Result, ty::UniverseIndex> { - match self.inner.borrow_mut().const_unification_table().probe_value(vid).val { + match self.inner.borrow_mut().const_unification_table().probe_value(vid) { ConstVariableValue::Known { value } => Ok(value), - ConstVariableValue::Unknown { universe } => Err(universe), + ConstVariableValue::Unknown { origin: _, universe } => Err(universe), } } @@ -1709,7 +1703,7 @@ impl<'tcx> InferCtxt<'tcx> { // `ty::ConstKind::Infer(ty::InferConst::Var(v))`. // // Not `inlined_probe_value(v)` because this call site is colder. - match self.inner.borrow_mut().const_unification_table().probe_value(v).val { + match self.inner.borrow_mut().const_unification_table().probe_value(v) { ConstVariableValue::Unknown { .. } => false, ConstVariableValue::Known { .. } => true, } @@ -1876,7 +1870,6 @@ impl<'a, 'tcx> TypeFolder> for ShallowResolver<'a, 'tcx> { .borrow_mut() .const_unification_table() .probe_value(vid) - .val .known() .unwrap_or(ct), ty::ConstKind::Infer(InferConst::EffectVar(vid)) => self diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 4b254fc7df518..9e1dab12b4d43 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -30,14 +30,12 @@ use super::sub::Sub; use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; use rustc_middle::infer::canonical::OriginalQueryValues; -use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVarValue}; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{AliasRelationDirection, TyVar}; use rustc_middle::ty::{IntType, UintType}; -use rustc_span::DUMMY_SP; #[derive(Clone)] pub struct CombineFields<'infcx, 'tcx> { @@ -328,8 +326,12 @@ impl<'tcx> InferCtxt<'tcx> { ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - let span = - self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span; + let span = match self.inner.borrow_mut().const_unification_table().probe_value(target_vid) { + ConstVariableValue::Known { value } => { + bug!("instantiating a known const var: {target_vid:?} {value} {ct}") + } + ConstVariableValue::Unknown { origin, universe: _ } => origin.span, + }; // FIXME(generic_const_exprs): Occurs check failures for unevaluated // constants and generic expressions are not yet handled correctly. let Generalization { value_may_be_infer: value, needs_wf: _ } = generalize::generalize( @@ -340,16 +342,10 @@ impl<'tcx> InferCtxt<'tcx> { ty::Variance::Invariant, )?; - self.inner.borrow_mut().const_unification_table().union_value( - target_vid, - ConstVarValue { - origin: ConstVariableOrigin { - kind: ConstVariableOriginKind::ConstInference, - span: DUMMY_SP, - }, - val: ConstVariableValue::Known { value }, - }, - ); + self.inner + .borrow_mut() + .const_unification_table() + .union_value(target_vid, ConstVariableValue::Known { value }); Ok(value) } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 27d37fd93697e..417c8695e248b 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -3,7 +3,7 @@ use std::mem; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; -use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; +use rustc_middle::infer::unify_key::ConstVariableValue; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::MaxUniverse; @@ -431,22 +431,19 @@ where let mut inner = self.infcx.inner.borrow_mut(); let variable_table = &mut inner.const_unification_table(); - let var_value = variable_table.probe_value(vid); - match var_value.val { + match variable_table.probe_value(vid) { ConstVariableValue::Known { value: u } => { drop(inner); self.relate(u, u) } - ConstVariableValue::Unknown { universe } => { + ConstVariableValue::Unknown { origin, universe } => { if self.for_universe.can_name(universe) { Ok(c) } else { let new_var_id = variable_table - .new_key(ConstVarValue { - origin: var_value.origin, - val: ConstVariableValue::Unknown { - universe: self.for_universe, - }, + .new_key(ConstVariableValue::Unknown { + origin, + universe: self.for_universe, }) .vid; Ok(ty::Const::new_var(self.tcx(), new_var_id, c.ty())) diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index f317ccee6918a..959b09031277c 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -1,12 +1,8 @@ -use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use super::{FixupError, FixupResult, InferCtxt, Span}; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use super::{FixupError, FixupResult, InferCtxt}; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable}; -use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitableExt, TypeVisitor}; +use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; -use std::ops::ControlFlow; - /////////////////////////////////////////////////////////////////////////// // OPPORTUNISTIC VAR RESOLVER @@ -104,88 +100,6 @@ impl<'a, 'tcx> TypeFolder> for OpportunisticRegionResolver<'a, 'tcx } } -/////////////////////////////////////////////////////////////////////////// -// UNRESOLVED TYPE FINDER - -/// The unresolved type **finder** walks a type searching for -/// type variables that don't yet have a value. The first unresolved type is stored. -/// It does not construct the fully resolved type (which might -/// involve some hashing and so forth). -pub struct UnresolvedTypeOrConstFinder<'a, 'tcx> { - infcx: &'a InferCtxt<'tcx>, -} - -impl<'a, 'tcx> UnresolvedTypeOrConstFinder<'a, 'tcx> { - pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { - UnresolvedTypeOrConstFinder { infcx } - } -} - -impl<'a, 'tcx> TypeVisitor> for UnresolvedTypeOrConstFinder<'a, 'tcx> { - type BreakTy = (ty::Term<'tcx>, Option); - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - let t = self.infcx.shallow_resolve(t); - if let ty::Infer(infer_ty) = *t.kind() { - // Since we called `shallow_resolve` above, this must - // be an (as yet...) unresolved inference variable. - let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty { - let mut inner = self.infcx.inner.borrow_mut(); - let ty_vars = &inner.type_variables(); - if let TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeParameterDefinition(_, _), - span, - } = ty_vars.var_origin(ty_vid) - { - Some(span) - } else { - None - } - } else { - None - }; - ControlFlow::Break((t.into(), ty_var_span)) - } else if !t.has_non_region_infer() { - // All const/type variables in inference types must already be resolved, - // no need to visit the contents. - ControlFlow::Continue(()) - } else { - // Otherwise, keep visiting. - t.super_visit_with(self) - } - } - - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { - let ct = self.infcx.shallow_resolve(ct); - if let ty::ConstKind::Infer(i) = ct.kind() { - // Since we called `shallow_resolve` above, this must - // be an (as yet...) unresolved inference variable. - let ct_var_span = if let ty::InferConst::Var(vid) = i { - let mut inner = self.infcx.inner.borrow_mut(); - let ct_vars = &mut inner.const_unification_table(); - if let ConstVariableOrigin { - span, - kind: ConstVariableOriginKind::ConstParameterDefinition(_, _), - } = ct_vars.probe_value(vid).origin - { - Some(span) - } else { - None - } - } else { - None - }; - ControlFlow::Break((ct.into(), ct_var_span)) - } else if !ct.has_non_region_infer() { - // All const/type variables in inference types must already be resolved, - // no need to visit the contents. - ControlFlow::Continue(()) - } else { - // Otherwise, keep visiting. - ct.super_visit_with(self) - } - } -} - /////////////////////////////////////////////////////////////////////////// // FULL TYPE RESOLUTION diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index abec12f52a6e6..0a632c4d12ad5 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -59,6 +59,9 @@ pub enum EscapeError { /// Non-ascii character in byte literal, byte string literal, or raw byte string literal. NonAsciiCharInByte, + // `\0` in a C string literal. + NulInCStr, + /// After a line ending with '\', the next line contains whitespace /// characters that are not skipped. UnskippedWhitespaceWarning, @@ -122,10 +125,20 @@ where { match mode { CStr => { - unescape_non_raw_common(src, mode, callback); + unescape_non_raw_common(src, mode, &mut |r, mut result| { + if let Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) = result { + result = Err(EscapeError::NulInCStr); + } + callback(r, result) + }); } RawCStr => { - check_raw_common(src, mode, &mut |r, result| callback(r, result.map(CStrUnit::Char))); + check_raw_common(src, mode, &mut |r, mut result| { + if let Ok('\0') = result { + result = Err(EscapeError::NulInCStr); + } + callback(r, result.map(CStrUnit::Char)) + }); } Char | Byte | Str | RawStr | ByteStr | RawByteStr => unreachable!(), } diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 6e50e89404648..c35799ef47f2b 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -120,7 +120,7 @@ pub enum ConstVariableOriginKind { #[derive(Copy, Clone, Debug)] pub enum ConstVariableValue<'tcx> { Known { value: ty::Const<'tcx> }, - Unknown { universe: ty::UniverseIndex }, + Unknown { origin: ConstVariableOrigin, universe: ty::UniverseIndex }, } impl<'tcx> ConstVariableValue<'tcx> { @@ -134,12 +134,6 @@ impl<'tcx> ConstVariableValue<'tcx> { } } -#[derive(Copy, Clone, Debug)] -pub struct ConstVarValue<'tcx> { - pub origin: ConstVariableOrigin, - pub val: ConstVariableValue<'tcx>, -} - #[derive(PartialEq, Copy, Clone, Debug)] pub struct ConstVidKey<'tcx> { pub vid: ty::ConstVid, @@ -153,7 +147,7 @@ impl<'tcx> From for ConstVidKey<'tcx> { } impl<'tcx> UnifyKey for ConstVidKey<'tcx> { - type Value = ConstVarValue<'tcx>; + type Value = ConstVariableValue<'tcx>; #[inline] fn index(&self) -> u32 { self.vid.as_u32() @@ -167,23 +161,23 @@ impl<'tcx> UnifyKey for ConstVidKey<'tcx> { } } -impl<'tcx> UnifyValue for ConstVarValue<'tcx> { +impl<'tcx> UnifyValue for ConstVariableValue<'tcx> { type Error = NoError; fn unify_values(&value1: &Self, &value2: &Self) -> Result { - Ok(match (value1.val, value2.val) { + match (value1, value2) { (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => { bug!("equating two const variables, both of which have known values") } // If one side is known, prefer that one. - (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => value1, - (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => value2, + (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => Ok(value1), + (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => Ok(value2), // If both sides are *unknown*, it hardly matters, does it? ( - ConstVariableValue::Unknown { universe: universe1 }, - ConstVariableValue::Unknown { universe: universe2 }, + ConstVariableValue::Unknown { origin, universe: universe1 }, + ConstVariableValue::Unknown { origin: _, universe: universe2 }, ) => { // If we unify two unbound variables, ?T and ?U, then whatever // value they wind up taking (which must be the same value) must @@ -191,12 +185,9 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> { // universe is the minimum of the two universes, because that is // the one which contains the fewest names in scope. let universe = cmp::min(universe1, universe2); - ConstVarValue { - val: ConstVariableValue::Unknown { universe }, - origin: value1.origin, - } + Ok(ConstVariableValue::Unknown { origin, universe }) } - }) + } } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 239929a2c0ef6..2cf6410990e8d 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -142,15 +142,17 @@ fn dump_matched_mir_node<'tcx, F>( } } -/// Returns the file basename portion (without extension) of a filename path -/// where we should dump a MIR representation output files. -fn dump_file_basename<'tcx>( +/// Returns the path to the filename where we should dump a given MIR. +/// Also used by other bits of code (e.g., NLL inference) that dump +/// graphviz data or other things. +fn dump_path<'tcx>( tcx: TyCtxt<'tcx>, + extension: &str, pass_num: bool, pass_name: &str, disambiguator: &dyn Display, body: &Body<'tcx>, -) -> String { +) -> PathBuf { let source = body.source; let promotion_id = match source.promoted { Some(id) => format!("-{id:?}"), @@ -186,32 +188,31 @@ fn dump_file_basename<'tcx>( _ => String::new(), }; - format!( - "{crate_name}.{item_name}{shim_disambiguator}{promotion_id}{pass_num}.{pass_name}.{disambiguator}", - ) -} - -/// Returns the path to the filename where we should dump a given MIR. -/// Also used by other bits of code (e.g., NLL inference) that dump -/// graphviz data or other things. -fn dump_path(tcx: TyCtxt<'_>, basename: &str, extension: &str) -> PathBuf { let mut file_path = PathBuf::new(); file_path.push(Path::new(&tcx.sess.opts.unstable_opts.dump_mir_dir)); - let file_name = format!("{basename}.{extension}",); + let file_name = format!( + "{crate_name}.{item_name}{shim_disambiguator}{promotion_id}{pass_num}.{pass_name}.{disambiguator}.{extension}", + ); file_path.push(&file_name); file_path } -/// Attempts to open the MIR dump file with the given name and extension. -fn create_dump_file_with_basename( - tcx: TyCtxt<'_>, - file_basename: &str, +/// Attempts to open a file where we should dump a given MIR or other +/// bit of MIR-related data. Used by `mir-dump`, but also by other +/// bits of code (e.g., NLL inference) that dump graphviz data or +/// other things, and hence takes the extension as an argument. +pub fn create_dump_file<'tcx>( + tcx: TyCtxt<'tcx>, extension: &str, + pass_num: bool, + pass_name: &str, + disambiguator: &dyn Display, + body: &Body<'tcx>, ) -> io::Result> { - let file_path = dump_path(tcx, file_basename, extension); + let file_path = dump_path(tcx, extension, pass_num, pass_name, disambiguator, body); if let Some(parent) = file_path.parent() { fs::create_dir_all(parent).map_err(|e| { io::Error::new( @@ -225,25 +226,6 @@ fn create_dump_file_with_basename( })?)) } -/// Attempts to open a file where we should dump a given MIR or other -/// bit of MIR-related data. Used by `mir-dump`, but also by other -/// bits of code (e.g., NLL inference) that dump graphviz data or -/// other things, and hence takes the extension as an argument. -pub fn create_dump_file<'tcx>( - tcx: TyCtxt<'tcx>, - extension: &str, - pass_num: bool, - pass_name: &str, - disambiguator: &dyn Display, - body: &Body<'tcx>, -) -> io::Result> { - create_dump_file_with_basename( - tcx, - &dump_file_basename(tcx, pass_num, pass_name, disambiguator, body), - extension, - ) -} - /////////////////////////////////////////////////////////////////////////// // Whole MIR bodies diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 63f4bab7914ed..bb1b96ed0e750 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -7,6 +7,7 @@ use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; use rustc_data_structures::intern::Interned; +use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; @@ -20,6 +21,7 @@ use std::marker::PhantomData; use std::mem; use std::num::NonZeroUsize; use std::ops::{ControlFlow, Deref}; +use std::ptr::NonNull; /// An entity in the Rust type system, which can be one of /// several kinds (types, lifetimes, and consts). @@ -31,10 +33,29 @@ use std::ops::{ControlFlow, Deref}; /// `Region` and `Const` are all interned. #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct GenericArg<'tcx> { - ptr: NonZeroUsize, + ptr: NonNull<()>, marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>, } +#[cfg(parallel_compiler)] +unsafe impl<'tcx> DynSend for GenericArg<'tcx> where + &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): DynSend +{ +} +#[cfg(parallel_compiler)] +unsafe impl<'tcx> DynSync for GenericArg<'tcx> where + &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): DynSync +{ +} +unsafe impl<'tcx> Send for GenericArg<'tcx> where + &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): Send +{ +} +unsafe impl<'tcx> Sync for GenericArg<'tcx> where + &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): Sync +{ +} + impl<'tcx> IntoDiagnosticArg for GenericArg<'tcx> { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { self.to_string().into_diagnostic_arg() @@ -60,21 +81,21 @@ impl<'tcx> GenericArgKind<'tcx> { GenericArgKind::Lifetime(lt) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*lt.0.0) & TAG_MASK, 0); - (REGION_TAG, lt.0.0 as *const ty::RegionKind<'tcx> as usize) + (REGION_TAG, NonNull::from(lt.0.0).cast()) } GenericArgKind::Type(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) + (TYPE_TAG, NonNull::from(ty.0.0).cast()) } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); - (CONST_TAG, ct.0.0 as *const WithCachedTypeInfo> as usize) + (CONST_TAG, NonNull::from(ct.0.0).cast()) } }; - GenericArg { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } + GenericArg { ptr: ptr.map_addr(|addr| addr | tag), marker: PhantomData } } } @@ -123,20 +144,22 @@ impl<'tcx> From> for GenericArg<'tcx> { impl<'tcx> GenericArg<'tcx> { #[inline] pub fn unpack(self) -> GenericArgKind<'tcx> { - let ptr = self.ptr.get(); + let ptr = unsafe { + self.ptr.map_addr(|addr| NonZeroUsize::new_unchecked(addr.get() & !TAG_MASK)) + }; // SAFETY: use of `Interned::new_unchecked` here is ok because these // pointers were originally created from `Interned` types in `pack()`, // and this is just going in the other direction. unsafe { - match ptr & TAG_MASK { + match self.ptr.addr().get() & TAG_MASK { REGION_TAG => GenericArgKind::Lifetime(ty::Region(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), + ptr.cast::>().as_ref(), ))), TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), + ptr.cast::>>().as_ref(), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), + ptr.cast::>>().as_ref(), ))), _ => intrinsics::unreachable(), } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ad9296a4cc88a..14a1681dd550f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -37,6 +37,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; +use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_data_structures::unord::UnordMap; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey}; @@ -63,6 +64,7 @@ use std::marker::PhantomData; use std::mem; use std::num::NonZeroUsize; use std::ops::ControlFlow; +use std::ptr::NonNull; use std::{fmt, str}; pub use crate::ty::diagnostics::*; @@ -848,10 +850,17 @@ pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Term<'tcx> { - ptr: NonZeroUsize, + ptr: NonNull<()>, marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>, } +#[cfg(parallel_compiler)] +unsafe impl<'tcx> DynSend for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): DynSend {} +#[cfg(parallel_compiler)] +unsafe impl<'tcx> DynSync for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): DynSync {} +unsafe impl<'tcx> Send for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): Send {} +unsafe impl<'tcx> Sync for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): Sync {} + impl Debug for Term<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let data = if let Some(ty) = self.ty() { @@ -914,17 +923,19 @@ impl<'tcx, D: TyDecoder>> Decodable for Term<'tcx> { impl<'tcx> Term<'tcx> { #[inline] pub fn unpack(self) -> TermKind<'tcx> { - let ptr = self.ptr.get(); + let ptr = unsafe { + self.ptr.map_addr(|addr| NonZeroUsize::new_unchecked(addr.get() & !TAG_MASK)) + }; // SAFETY: use of `Interned::new_unchecked` here is ok because these // pointers were originally created from `Interned` types in `pack()`, // and this is just going in the other direction. unsafe { - match ptr & TAG_MASK { + match self.ptr.addr().get() & TAG_MASK { TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), + ptr.cast::>>().as_ref(), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), + ptr.cast::>>().as_ref(), ))), _ => core::intrinsics::unreachable(), } @@ -986,16 +997,16 @@ impl<'tcx> TermKind<'tcx> { TermKind::Ty(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) + (TYPE_TAG, NonNull::from(ty.0.0).cast()) } TermKind::Const(ct) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); - (CONST_TAG, ct.0.0 as *const WithCachedTypeInfo> as usize) + (CONST_TAG, NonNull::from(ct.0.0).cast()) } }; - Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } + Term { ptr: ptr.map_addr(|addr| addr | tag), marker: PhantomData } } } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index d515e86a18296..fb19bb996f922 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -616,6 +616,8 @@ parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||` +parse_nul_in_c_str = null characters in C string literals are not supported + parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings parse_out_of_range_hex_escape = out of range hex escape diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 34b34a1bad6c9..7dc711d96109d 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2163,6 +2163,11 @@ pub enum UnescapeError { #[subdiagnostic] suggestion: MoreThanOneCharSugg, }, + #[diag(parse_nul_in_c_str)] + NulInCStr { + #[primary_span] + span: Span, + }, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index fbc77f2878081..3238f8e23bb0a 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -262,6 +262,9 @@ pub(crate) fn emit_unescape_error( EscapeError::LoneSlash => { dcx.emit_err(UnescapeError::LoneSlash(err_span)); } + EscapeError::NulInCStr => { + dcx.emit_err(UnescapeError::NulInCStr { span: err_span }); + } EscapeError::UnskippedWhitespaceWarning => { let (c, char_span) = last_char(); dcx.emit_warn(UnescapeError::UnskippedWhitespace { diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 53bdef6dfa0fb..af8c962a2ed6a 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -75,8 +75,6 @@ session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be u session_not_supported = not supported -session_nul_in_c_str = null characters in C string literals are not supported - session_octal_float_literal_not_supported = octal float literal is not supported session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg} diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 21a206798af18..e19f0fd84de56 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -6,7 +6,7 @@ use rustc_errors::{ error_code, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan, }; use rustc_macros::Diagnostic; -use rustc_span::{BytePos, Span, Symbol}; +use rustc_span::{Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; use crate::parse::ParseSess; @@ -346,13 +346,6 @@ pub(crate) struct BinaryFloatLiteralNotSupported { pub span: Span, } -#[derive(Diagnostic)] -#[diag(session_nul_in_c_str)] -pub(crate) struct NulInCStr { - #[primary_span] - pub span: Span, -} - pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) { // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { @@ -432,12 +425,6 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: }; dcx.emit_err(IntLiteralTooLarge { span, limit }); } - LitError::NulInCStr(range) => { - let lo = BytePos(span.lo().0 + range.start as u32 + 2); - let hi = BytePos(span.lo().0 + range.end as u32 + 2); - let span = span.with_lo(lo).with_hi(hi); - dcx.emit_err(NulInCStr { span }); - } } } diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 4bac98909add0..b99640d2f2d68 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -190,35 +190,120 @@ where stable_mir::compiler_interface::run(&tables, || init(&tables, f)) } +/// Instantiate and run the compiler with the provided arguments and callback. +/// +/// The callback will be invoked after the compiler ran all its analyses, but before code generation. +/// Note that this macro accepts two different formats for the callback: +/// 1. An ident that resolves to a function that accepts no argument and returns `ControlFlow` +/// ```ignore(needs-extern-crate) +/// # extern crate rustc_driver; +/// # extern crate rustc_interface; +/// # #[macro_use] +/// # extern crate rustc_smir; +/// # extern crate stable_mir; +/// # +/// # fn main() { +/// # use std::ops::ControlFlow; +/// # use stable_mir::CompilerError; +/// fn analyze_code() -> ControlFlow<(), ()> { +/// // Your code goes in here. +/// # ControlFlow::Continue(()) +/// } +/// # let args = vec!["--verbose".to_string()]; +/// let result = run!(args, analyze_code); +/// # assert_eq!(result, Err(CompilerError::Skipped)) +/// # } +/// ``` +/// 2. A closure expression: +/// ```ignore(needs-extern-crate) +/// # extern crate rustc_driver; +/// # extern crate rustc_interface; +/// # #[macro_use] +/// # extern crate rustc_smir; +/// # extern crate stable_mir; +/// # +/// # fn main() { +/// # use std::ops::ControlFlow; +/// # use stable_mir::CompilerError; +/// fn analyze_code(extra_args: Vec) -> ControlFlow<(), ()> { +/// # let _ = extra_args; +/// // Your code goes in here. +/// # ControlFlow::Continue(()) +/// } +/// # let args = vec!["--verbose".to_string()]; +/// # let extra_args = vec![]; +/// let result = run!(args, || analyze_code(extra_args)); +/// # assert_eq!(result, Err(CompilerError::Skipped)) +/// # } +/// ``` #[macro_export] macro_rules! run { + ($args:expr, $callback_fn:ident) => { + run_driver!($args, || $callback_fn()) + }; + ($args:expr, $callback:expr) => { + run_driver!($args, $callback) + }; +} + +/// Instantiate and run the compiler with the provided arguments and callback. +/// +/// This is similar to `run` but it invokes the callback with the compiler's `TyCtxt`, +/// which can be used to invoke internal APIs. +#[macro_export] +macro_rules! run_with_tcx { + ($args:expr, $callback_fn:ident) => { + run_driver!($args, |tcx| $callback_fn(tcx), with_tcx) + }; ($args:expr, $callback:expr) => { - run!($args, tcx, $callback) + run_driver!($args, $callback, with_tcx) + }; +} + +/// Optionally include an ident. This is needed due to macro hygiene. +#[macro_export] +#[doc(hidden)] +macro_rules! optional { + (with_tcx $ident:ident) => { + $ident }; - ($args:expr, $tcx:ident, $callback:expr) => {{ +} + +/// Prefer using [run!] and [run_with_tcx] instead. +/// +/// This macro implements the instantiation of a StableMIR driver, and it will invoke +/// the given callback after the compiler analyses. +/// +/// The third argument determines whether the callback requires `tcx` as an argument. +#[macro_export] +#[doc(hidden)] +macro_rules! run_driver { + ($args:expr, $callback:expr $(, $with_tcx:ident)?) => {{ use rustc_driver::{Callbacks, Compilation, RunCompiler}; use rustc_interface::{interface, Queries}; use stable_mir::CompilerError; use std::ops::ControlFlow; - pub struct StableMir + pub struct StableMir ControlFlow> where B: Send, C: Send, + F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { args: Vec, - callback: fn(TyCtxt<'_>) -> ControlFlow, + callback: Option, result: Option>, } - impl StableMir + impl StableMir where B: Send, C: Send, + F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { /// Creates a new `StableMir` instance, with given test_function and arguments. - pub fn new(args: Vec, callback: fn(TyCtxt<'_>) -> ControlFlow) -> Self { - StableMir { args, callback, result: None } + pub fn new(args: Vec, callback: F) -> Self { + StableMir { args, callback: Some(callback), result: None } } /// Runs the compiler against given target and tests it with `test_function` @@ -238,10 +323,11 @@ macro_rules! run { } } - impl Callbacks for StableMir + impl Callbacks for StableMir where B: Send, C: Send, + F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { /// Called after analysis. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) @@ -251,20 +337,24 @@ macro_rules! run { queries: &'tcx Queries<'tcx>, ) -> Compilation { queries.global_ctxt().unwrap().enter(|tcx| { - rustc_internal::run(tcx, || { - self.result = Some((self.callback)(tcx)); - }) - .unwrap(); - if self.result.as_ref().is_some_and(|val| val.is_continue()) { - Compilation::Continue + if let Some(callback) = self.callback.take() { + rustc_internal::run(tcx, || { + self.result = Some(callback($(optional!($with_tcx tcx))?)); + }) + .unwrap(); + if self.result.as_ref().is_some_and(|val| val.is_continue()) { + Compilation::Continue + } else { + Compilation::Stop + } } else { - Compilation::Stop + Compilation::Continue } }) } } - StableMir::new($args, |$tcx| $callback).run() + StableMir::new($args, $callback).run() }}; } diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index f47ec49df1d9f..aa25f82ae1d8d 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -369,6 +369,7 @@ fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str { "non-ASCII character in byte string literal" } EscapeError::NonAsciiCharInByte => "non-ASCII character in raw byte string literal", + EscapeError::NulInCStr => "null character in C string literal", EscapeError::UnskippedWhitespaceWarning => "", EscapeError::MultipleSkippedLinesWarning => "", } diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index 6c6916c585f1f..69dffbf79f191 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -106,6 +106,9 @@ fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> (&'static str, EE::NonAsciiCharInByte => { "Byte literals must not contain non-ASCII characters" } + EE::NulInCStr => { + "C strings literals must not contain null characters" + } EE::UnskippedWhitespaceWarning => "Whitespace after this escape is not skipped", EE::MultipleSkippedLinesWarning => "Multiple lines are skipped by this escape", diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs index 30b42bc3bfafc..7d7469597afc2 100644 --- a/tests/ui-fulldeps/stable-mir/check_abi.rs +++ b/tests/ui-fulldeps/stable-mir/check_abi.rs @@ -12,14 +12,12 @@ #![feature(ascii_char, ascii_char_variants)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::abi::{ArgAbi, CallConvention, FieldsShape, PassMode, VariantsShape}; use stable_mir::mir::mono::Instance; @@ -32,7 +30,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { // Find items in the local crate. let items = stable_mir::all_local_items(); @@ -117,7 +115,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs index 93def93127c88..fb5e13eb13b10 100644 --- a/tests/ui-fulldeps/stable-mir/check_allocation.rs +++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs @@ -14,14 +14,12 @@ #![feature(ascii_char, ascii_char_variants)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::crate_def::CrateDef; use stable_mir::mir::alloc::GlobalAlloc; @@ -40,7 +38,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { // Find items in the local crate. let items = stable_mir::all_local_items(); check_foo(*get_item(&items, (ItemKind::Static, "FOO")).unwrap()); @@ -230,7 +228,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs index e9a2599d8732c..4a124adb2b605 100644 --- a/tests/ui-fulldeps/stable-mir/check_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_defs.rs @@ -11,7 +11,6 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -20,7 +19,6 @@ extern crate stable_mir; use std::assert_matches::assert_matches; use mir::{mono::Instance, TerminatorKind::*}; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind, Ty, UintTy}; use stable_mir::*; @@ -30,7 +28,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { let entry = stable_mir::entry_fn().unwrap(); let main_fn = Instance::try_from(entry).unwrap(); assert_eq!(main_fn.name(), "main"); @@ -113,7 +111,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index 5cb07eabf41d3..1e039e5ae514c 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -11,7 +11,6 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -19,7 +18,6 @@ extern crate rustc_interface; extern crate stable_mir; use mir::{mono::Instance, TerminatorKind::*}; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind}; use stable_mir::*; @@ -29,7 +27,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { let items = stable_mir::all_local_items(); // Get all items and split generic vs monomorphic items. @@ -96,7 +94,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_item_kind.rs b/tests/ui-fulldeps/stable-mir/check_item_kind.rs index 72e0e09e6e363..0a7f00029f2ac 100644 --- a/tests/ui-fulldeps/stable-mir/check_item_kind.rs +++ b/tests/ui-fulldeps/stable-mir/check_item_kind.rs @@ -11,14 +11,12 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::*; use std::io::Write; @@ -27,7 +25,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_item_kind(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_item_kind() -> ControlFlow<()> { let items = stable_mir::all_local_items(); assert_eq!(items.len(), 4); // Constructor item. @@ -59,7 +57,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_item_kind(tcx)).unwrap(); + run!(args, test_item_kind).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs index fb1197e4ecc40..c9fbe15ffb03f 100644 --- a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs +++ b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs @@ -11,14 +11,12 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::CrateDef; use std::collections::HashSet; @@ -83,7 +81,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, test_traits()).unwrap(); + run!(args, test_traits).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs index b90d47d4540ba..14cbf9e9f81f1 100644 --- a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs +++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs @@ -12,14 +12,12 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind, Ty, }; use stable_mir::mir::{Body, MirVisitor, FieldIdx, Place, ProjectionElem, visit::{Location, @@ -30,7 +28,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { let main_fn = stable_mir::entry_fn(); let body = main_fn.unwrap().body(); let mut visitor = PlaceVisitor{ body: &body, tested: false}; @@ -87,7 +85,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs index fc56e24814b04..e6dd9fa132d83 100644 --- a/tests/ui-fulldeps/stable-mir/compilation-result.rs +++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs @@ -10,14 +10,12 @@ #![feature(rustc_private)] #![feature(assert_matches)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use std::io::Write; @@ -32,33 +30,41 @@ fn main() { test_continue(args.clone()); test_break(args.clone()); test_failed(args.clone()); - test_skipped(args); + test_skipped(args.clone()); + test_captured(args) } fn test_continue(args: Vec) { - let result = run!(args, ControlFlow::Continue::<(), bool>(true)); + let result = run!(args, || ControlFlow::Continue::<(), bool>(true)); assert_eq!(result, Ok(true)); } fn test_break(args: Vec) { - let result = run!(args, ControlFlow::Break::(false)); + let result = run!(args, || ControlFlow::Break::(false)); assert_eq!(result, Err(stable_mir::CompilerError::Interrupted(false))); } #[allow(unreachable_code)] fn test_skipped(mut args: Vec) { args.push("--version".to_string()); - let result = run!(args, unreachable!() as ControlFlow<()>); + let result = run!(args, || unreachable!() as ControlFlow<()>); assert_eq!(result, Err(stable_mir::CompilerError::Skipped)); } #[allow(unreachable_code)] fn test_failed(mut args: Vec) { args.push("--cfg=broken".to_string()); - let result = run!(args, unreachable!() as ControlFlow<()>); + let result = run!(args, || unreachable!() as ControlFlow<()>); assert_eq!(result, Err(stable_mir::CompilerError::CompilationFailed)); } +/// Test that we are able to pass a closure and set the return according to the captured value. +fn test_captured(args: Vec) { + let captured = "10".to_string(); + let result = run!(args, || ControlFlow::Continue::<(), usize>(captured.len())); + assert_eq!(result, Ok(captured.len())); +} + fn generate_input(path: &str) -> std::io::Result<()> { let mut file = std::fs::File::create(path)?; write!( diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index c2035430a33b8..8258883436f2f 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -12,7 +12,6 @@ #![feature(control_flow_enum)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -20,7 +19,6 @@ extern crate rustc_interface; extern crate stable_mir; use rustc_hir::def::DefKind; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ItemKind; use stable_mir::crate_def::CrateDef; @@ -33,7 +31,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { // Get the local crate using stable_mir API. let local = stable_mir::local_crate(); assert_eq!(&local.name, CRATE_NAME); @@ -194,7 +192,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs index 8c3fda7b6bb1f..40f2d901a2b23 100644 --- a/tests/ui-fulldeps/stable-mir/projections.rs +++ b/tests/ui-fulldeps/stable-mir/projections.rs @@ -12,14 +12,12 @@ #![feature(control_flow_enum)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::crate_def::CrateDef; use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind}; @@ -32,7 +30,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// Tests projections within Place objects -fn test_place_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_place_projections() -> ControlFlow<()> { let items = stable_mir::all_local_items(); let body = get_item(&items, (ItemKind::Fn, "projections")).unwrap().body(); assert_eq!(body.blocks.len(), 4); @@ -159,7 +157,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_place_projections(tcx)).unwrap(); + run!(args, test_place_projections).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs index b0596b1882383..b4faaeb4fc06d 100644 --- a/tests/ui-fulldeps/stable-mir/smir_internal.rs +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -26,7 +26,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; -fn test_translation(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_translation(_tcx: TyCtxt) -> ControlFlow<()> { let main_fn = stable_mir::entry_fn().unwrap(); let body = main_fn.body(); let orig_ty = body.locals()[0].ty; @@ -48,7 +48,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_translation(tcx)).unwrap(); + run_with_tcx!(args, test_translation).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs index 027b0e7d9e85c..d7739770b706a 100644 --- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs +++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs @@ -11,7 +11,6 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -19,7 +18,6 @@ extern crate rustc_interface; extern crate stable_mir; use std::collections::HashSet; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::*; use stable_mir::mir::MirVisitor; @@ -28,7 +26,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; -fn test_visitor(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_visitor() -> ControlFlow<()> { let main_fn = stable_mir::entry_fn(); let main_body = main_fn.unwrap().body(); let main_visitor = TestVisitor::collect(&main_body); @@ -116,7 +114,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_visitor(tcx)).unwrap(); + run!(args, test_visitor).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui/async-await/inference_var_self_argument.rs b/tests/ui/async-await/inference_var_self_argument.rs new file mode 100644 index 0000000000000..fd8482f86b4fc --- /dev/null +++ b/tests/ui/async-await/inference_var_self_argument.rs @@ -0,0 +1,12 @@ +//! This is a regression test for an ICE. +// edition: 2021 + +trait Foo { + async fn foo(self: &dyn Foo) { + //~^ ERROR: `Foo` cannot be made into an object + //~| ERROR invalid `self` parameter type: &dyn Foo + todo!() + } +} + +fn main() {} diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr new file mode 100644 index 0000000000000..8a8c1ea03f14a --- /dev/null +++ b/tests/ui/async-await/inference_var_self_argument.stderr @@ -0,0 +1,28 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/inference_var_self_argument.rs:5:5 + | +LL | async fn foo(self: &dyn Foo) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/inference_var_self_argument.rs:5:14 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | async fn foo(self: &dyn Foo) { + | ^^^ ...because method `foo` is `async` + = help: consider moving `foo` to another trait + +error[E0307]: invalid `self` parameter type: &dyn Foo + --> $DIR/inference_var_self_argument.rs:5:24 + | +LL | async fn foo(self: &dyn Foo) { + | ^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0307. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/erroneous_signature.rs b/tests/ui/object-safety/erroneous_signature.rs new file mode 100644 index 0000000000000..cc1841cc4b2a1 --- /dev/null +++ b/tests/ui/object-safety/erroneous_signature.rs @@ -0,0 +1,17 @@ +trait Foo { + fn err(&self) -> MissingType; + //~^ ERROR cannot find type `MissingType` in this scope +} + +impl Foo for i32 { + fn err(&self) -> MissingType { + //~^ ERROR cannot find type `MissingType` in this scope + 0 + } +} + +fn coerce(x: &i32) -> &dyn Foo { + x +} + +fn main() {} diff --git a/tests/ui/object-safety/erroneous_signature.stderr b/tests/ui/object-safety/erroneous_signature.stderr new file mode 100644 index 0000000000000..f3b14ffe34c3b --- /dev/null +++ b/tests/ui/object-safety/erroneous_signature.stderr @@ -0,0 +1,15 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/erroneous_signature.rs:2:22 + | +LL | fn err(&self) -> MissingType; + | ^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/erroneous_signature.rs:7:22 + | +LL | fn err(&self) -> MissingType { + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs index e20ca50b88f90..2f9ca09f3a5de 100644 Binary files a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs and b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs differ diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr index ff9006f6f97f1..a05dea3ff07e6 100644 Binary files a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr and b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr differ diff --git a/triagebot.toml b/triagebot.toml index 2b818c0a990d0..bd14640e280e4 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -631,7 +631,7 @@ cc = ["@nnethercote"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "spastorino"] +users_on_vacation = ["jyn514"] [assign.adhoc_groups] compiler-team = [