Auto merge of #2804 - saethlin:rustup, r=RalfJung

Rustup
This commit is contained in:
bors 2023-03-05 17:37:09 +00:00
commit 9f3c3ffaf8
762 changed files with 14377 additions and 8645 deletions

View file

@ -322,7 +322,7 @@ jobs:
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
DIST_REQUIRE_ALL_TOOLS: 1
os: macos-latest
os: macos-12-xl
- name: dist-apple-various
env:
SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim"
@ -333,7 +333,7 @@ jobs:
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
os: macos-latest
os: macos-12-xl
- name: dist-x86_64-apple-alt
env:
SCRIPT: "./x.py dist bootstrap --include-default-paths"
@ -344,7 +344,7 @@ jobs:
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
os: macos-latest
os: macos-12-xl
- name: x86_64-apple-1
env:
SCRIPT: "./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps"
@ -355,7 +355,7 @@ jobs:
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
os: macos-latest
os: macos-12-xl
- name: x86_64-apple-2
env:
SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps"
@ -366,7 +366,7 @@ jobs:
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
os: macos-latest
os: macos-12-xl
- name: dist-aarch64-apple
env:
SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2"
@ -381,7 +381,7 @@ jobs:
NO_OVERFLOW_CHECKS: 1
DIST_REQUIRE_ALL_TOOLS: 1
JEMALLOC_SYS_WITH_LG_PAGE: 14
os: macos-latest
os: macos-12-xl
- name: x86_64-msvc-1
env:
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"

View file

@ -15,7 +15,7 @@ Adrien Tétar <adri-from-59@hotmail.fr>
Ahmed Charles <ahmedcharles@gmail.com> <acharles@outlook.com>
Alan Egerton <eggyal@gmail.com>
Alan Stoate <alan.stoate@gmail.com>
Albert Larsan <albert.larsan@gmail.com> Albert Larsan <74931857+albertlarsan68@users.noreply.github.com>
Albert Larsan <albert.larsan@gmail.com> <74931857+albertlarsan68@users.noreply.github.com>
Alessandro Decina <alessandro.d@gmail.com>
Alex Burka <durka42+github@gmail.com> Alex Burka <aburka@seas.upenn.edu>
Alex Hansen <ahansen2@trinity.edu>

View file

@ -1373,9 +1373,9 @@ dependencies = [
[[package]]
name = "ena"
version = "0.14.0"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3"
checksum = "b2e5d13ca2353ab7d0230988629def93914a8c4015f621f9b13ed2955614731d"
dependencies = [
"log",
]
@ -1922,15 +1922,6 @@ dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.3.0"
@ -2222,14 +2213,14 @@ dependencies = [
[[package]]
name = "is-terminal"
version = "0.4.2"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857"
dependencies = [
"hermit-abi 0.2.6",
"hermit-abi 0.3.0",
"io-lifetimes",
"rustix",
"windows-sys 0.42.0",
"windows-sys 0.45.0",
]
[[package]]
@ -2260,9 +2251,9 @@ dependencies = [
[[package]]
name = "jobserver"
version = "0.1.24"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
dependencies = [
"libc",
]
@ -2328,9 +2319,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.138"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
dependencies = [
"rustc-std-workspace-core",
]
@ -3810,6 +3801,8 @@ dependencies = [
"rustc_span",
"rustc_symbol_mangling",
"rustc_target",
"serde",
"serde_json",
"smallvec",
"tempfile",
"tracing",

View file

@ -1,5 +1,7 @@
# The Rust Programming Language
[![Rust Community](https://img.shields.io/badge/Rust_Community%20-Join_us-brightgreen?style=plastic&logo=rust)](https://www.rust-lang.org/community)
This is the main source code repository for [Rust]. It contains the compiler,
standard library, and documentation.

View file

@ -1505,14 +1505,6 @@ pub struct PointeeInfo {
pub safe: Option<PointerKind>,
}
/// Used in `might_permit_raw_init` to indicate the kind of initialisation
/// that is checked to be valid
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InitKind {
Zero,
UninitMitigated0x01Fill,
}
impl LayoutS {
/// Returns `true` if the layout corresponds to an unsized type.
pub fn is_unsized(&self) -> bool {

View file

@ -225,7 +225,7 @@ impl AssocOp {
AssignOp(_) | // `{ 42 } +=`
As | // `{ 42 } as usize`
// Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect
// NotEqual | // `{ 42 } != { 42 } struct literals parser recovery.
// NotEqual | // `{ 42 } != { 42 }` struct literals parser recovery.
Colon, // `{ 42 }: usize`
)
}

View file

@ -22,9 +22,6 @@ ast_lowering_misplaced_impl_trait =
ast_lowering_misplaced_assoc_ty_binding =
associated type bounds are only allowed in where clauses and function signatures, not in {$position}
ast_lowering_rustc_box_attribute_error =
#[rustc_box] requires precisely one argument and no other attributes are allowed
ast_lowering_underscore_expr_lhs_assign =
in expressions, `_` can only be used on the left-hand side of an assignment
.label = `_` not allowed here

View file

@ -87,13 +87,6 @@ pub struct MisplacedAssocTyBinding<'a> {
pub position: DiagnosticArgFromDisplay<'a>,
}
#[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering_rustc_box_attribute_error)]
pub struct RustcBoxAttributeError {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering_underscore_expr_lhs_assign)]
pub struct UnderscoreExprLhsAssign {

View file

@ -2,7 +2,7 @@ use super::errors::{
AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignemnt,
GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure,
RustcBoxAttributeError, UnderscoreExprLhsAssign,
UnderscoreExprLhsAssign,
};
use super::ResolverAstLoweringExt;
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
@ -83,15 +83,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
ExprKind::Call(f, args) => {
if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
if let [inner] = &args[..] && e.attrs.len() == 1 {
let kind = hir::ExprKind::Box(self.lower_expr(&inner));
return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
} else {
let guar = self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
hir::ExprKind::Err(guar)
}
} else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)
} else {
let f = self.lower_expr(f);

View file

@ -13,7 +13,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::PredicateOrigin;
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ty::{DefIdTree, ResolverAstLowering, TyCtxt};
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident};
@ -1339,13 +1339,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
.map(|predicate| self.lower_where_predicate(predicate)),
);
let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> =
self.lower_generic_params_mut(&generics.params).collect();
let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
.lower_generic_params_mut(&generics.params, hir::GenericParamSource::Generics)
.collect();
// Introduce extra lifetimes if late resolution tells us to.
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
self.lifetime_res_to_generic_param(ident, node_id, res)
self.lifetime_res_to_generic_param(
ident,
node_id,
res,
hir::GenericParamSource::Generics,
)
}));
let has_where_clause_predicates = !generics.where_clause.predicates.is_empty();
@ -1449,7 +1455,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
span,
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
hir_id: self.next_id(),
bound_generic_params: self.lower_generic_params(bound_generic_params),
bound_generic_params: self
.lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
bounded_ty: self
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {

View file

@ -804,6 +804,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ident: Ident,
node_id: NodeId,
res: LifetimeRes,
source: hir::GenericParamSource,
) -> Option<hir::GenericParam<'hir>> {
let (name, kind) = match res {
LifetimeRes::Param { .. } => {
@ -837,6 +838,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
source,
})
}
@ -852,11 +854,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
binder: NodeId,
generic_params: &[GenericParam],
) -> &'hir [hir::GenericParam<'hir>] {
let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect();
let mut generic_params: Vec<_> = self
.lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder)
.collect();
let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
debug!(?extra_lifetimes);
generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
self.lifetime_res_to_generic_param(ident, node_id, res)
self.lifetime_res_to_generic_param(ident, node_id, res, hir::GenericParamSource::Binder)
}));
let generic_params = self.arena.alloc_from_iter(generic_params);
debug!(?generic_params);
@ -1375,8 +1379,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span,
);
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
let (param, bounds, path) =
self.lower_generic_and_bounds(*def_node_id, span, ident, bounds);
let (param, bounds, path) = self.lower_universal_param_and_bounds(
*def_node_id,
span,
ident,
bounds,
);
self.impl_trait_defs.push(param);
if let Some(bounds) = bounds {
self.impl_trait_bounds.push(bounds);
@ -1530,6 +1538,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
source: hir::GenericParamSource::Generics,
}
},
));
@ -1598,7 +1607,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
}
/// Given a `parent_def_id`, a list of `lifetimes_in_bounds and a `remapping` hash to be
/// Given a `parent_def_id`, a list of `lifetimes_in_bounds` and a `remapping` hash to be
/// filled, this function creates new definitions for `Param` and `Fresh` lifetimes, inserts the
/// new definition, adds it to the remapping with the definition of the given lifetime and
/// returns a list of lifetimes to be lowered afterwards.
@ -1987,6 +1996,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
source: hir::GenericParamSource::Generics,
}
},
));
@ -2152,16 +2162,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_generic_params_mut<'s>(
&'s mut self,
params: &'s [GenericParam],
source: hir::GenericParamSource,
) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
params.iter().map(move |param| self.lower_generic_param(param))
params.iter().map(move |param| self.lower_generic_param(param, source))
}
fn lower_generic_params(&mut self, params: &[GenericParam]) -> &'hir [hir::GenericParam<'hir>] {
self.arena.alloc_from_iter(self.lower_generic_params_mut(params))
fn lower_generic_params(
&mut self,
params: &[GenericParam],
source: hir::GenericParamSource,
) -> &'hir [hir::GenericParam<'hir>] {
self.arena.alloc_from_iter(self.lower_generic_params_mut(params, source))
}
#[instrument(level = "trace", skip(self))]
fn lower_generic_param(&mut self, param: &GenericParam) -> hir::GenericParam<'hir> {
fn lower_generic_param(
&mut self,
param: &GenericParam,
source: hir::GenericParamSource,
) -> hir::GenericParam<'hir> {
let (name, kind) = self.lower_generic_param_kind(param);
let hir_id = self.lower_node_id(param.id);
@ -2174,6 +2193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: self.tcx.sess.contains_name(&param.attrs, sym::may_dangle),
kind,
colon_span: param.colon_span.map(|s| self.lower_span(s)),
source,
}
}
@ -2266,7 +2286,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
#[instrument(level = "debug", skip(self), ret)]
fn lower_generic_and_bounds(
fn lower_universal_param_and_bounds(
&mut self,
node_id: NodeId,
span: Span,
@ -2286,6 +2306,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span,
kind: hir::GenericParamKind::Type { default: None, synthetic: true },
colon_span: None,
source: hir::GenericParamSource::Generics,
};
let preds = self.lower_generic_bound_predicate(

View file

@ -12,7 +12,7 @@ use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
use rustc_ast::walk_list;
use rustc_ast::*;
use rustc_ast_pretty::pprust::{self, State};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::FxIndexMap;
use rustc_macros::Subdiagnostic;
use rustc_parse::validate_attr;
use rustc_session::lint::builtin::{
@ -192,7 +192,7 @@ impl<'a> AstValidator<'a> {
// We allow these:
// - `Option<impl Trait>`
// - `option::Option<impl Trait>`
// - `option::Option<T>::Foo<impl Trait>
// - `option::Option<T>::Foo<impl Trait>`
//
// But not these:
// - `<impl Trait>::Foo`
@ -643,7 +643,7 @@ fn validate_generic_param_order(
span: Span,
) {
let mut max_param: Option<ParamKindOrd> = None;
let mut out_of_order = FxHashMap::default();
let mut out_of_order = FxIndexMap::default();
let mut param_idents = Vec::with_capacity(generics.len());
for (idx, param) in generics.iter().enumerate() {

View file

@ -386,7 +386,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
).span_suggestion_verbose(
lhs.span.shrink_to_lo(),
"you might have meant to introduce a new binding",
"let ".to_string(),
"let ",
Applicability::MachineApplicable,
).emit();
}

View file

@ -4,7 +4,6 @@
//!
//! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`.
#![allow(rustc::potential_query_instability)]
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(iter_is_partitioned)]

View file

@ -6,7 +6,7 @@ use rustc_errors::{
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
use rustc_infer::infer::TyCtxtInferExt;
@ -236,10 +236,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let ty = used_place.ty(self.body, self.infcx.tcx).ty;
let needs_note = match ty.kind() {
ty::Closure(id, _) => {
let tables = self.infcx.tcx.typeck(id.expect_local());
let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(id.expect_local());
tables.closure_kind_origins().get(hir_id).is_none()
self.infcx.tcx.closure_kind_origin(id.expect_local()).is_none()
}
_ => true,
};
@ -1470,6 +1467,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Reports StorageDeadOrDrop of `place` conflicts with `borrow`.
///
/// Depending on the origin of the StorageDeadOrDrop, this may be
/// reported as either a drop or an illegal mutation of a borrowed value.
/// The latter is preferred when the this is a drop triggered by a
/// reassignment, as it's more user friendly to report a problem with the
/// explicit assignment than the implicit drop.
#[instrument(level = "debug", skip(self))]
pub(crate) fn report_storage_dead_or_drop_of_borrowed(
&mut self,
location: Location,
place_span: (Place<'tcx>, Span),
borrow: &BorrowData<'tcx>,
) {
// It's sufficient to check the last desugaring as Replace is the last
// one to be applied.
if let Some(DesugaringKind::Replace) = place_span.1.desugaring_kind() {
self.report_illegal_mutation_of_borrowed(location, place_span, borrow)
} else {
self.report_borrowed_value_does_not_live_long_enough(
location,
borrow,
place_span,
Some(WriteKind::StorageDeadOrDrop),
)
}
}
/// This means that some data referenced by `borrow` needs to live
/// past the point where the StorageDeadOrDrop of `place` occurs.
/// This is usually interpreted as meaning that `place` has too
@ -1670,7 +1693,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
format!("`{}` would have to be valid for `{}`...", name, region_name),
);
let fn_hir_id = self.mir_hir_id();
err.span_label(
drop_span,
format!(
@ -1678,19 +1700,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
name,
self.infcx
.tcx
.hir()
.opt_name(fn_hir_id)
.opt_item_name(self.mir_def_id().to_def_id())
.map(|name| format!("function `{}`", name))
.unwrap_or_else(|| {
match &self
.infcx
.tcx
.typeck(self.mir_def_id())
.node_type(fn_hir_id)
.kind()
{
ty::Closure(..) => "enclosing closure",
ty::Generator(..) => "enclosing generator",
match &self.infcx.tcx.def_kind(self.mir_def_id()) {
DefKind::Closure => "enclosing closure",
DefKind::Generator => "enclosing generator",
kind => bug!("expected closure or generator, found {:?}", kind),
}
.to_string()

View file

@ -13,7 +13,7 @@ use rustc_middle::mir::{
Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
};
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
use rustc_span::def_id::LocalDefId;
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
@ -115,11 +115,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
let did = did.expect_local();
let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
if let Some((span, hir_place)) =
self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
{
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
diag.span_note(
*span,
&format!(
@ -139,11 +135,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let Some(target) = target {
if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
let did = did.expect_local();
let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
if let Some((span, hir_place)) =
self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
{
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
diag.span_note(
*span,
&format!(
@ -373,14 +365,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
//
// We know the field exists so it's safe to call operator[] and `unwrap` here.
let def_id = def_id.expect_local();
let var_id = self
.infcx
.tcx
.typeck(def_id)
.closure_min_captures_flattened(def_id)
.nth(field.index())
.unwrap()
.get_root_variable();
let var_id =
self.infcx.tcx.closure_captures(def_id)[field.index()].get_root_variable();
Some(self.infcx.tcx.hir().name(var_id).to_string())
}
@ -939,7 +925,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return OtherUse(use_span);
}
for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
// drop and replace might have moved the assignment to the next block
let maybe_additional_statement =
if let TerminatorKind::Drop { target: drop_target, .. } =
self.body[location.block].terminator().kind
{
self.body[drop_target].statements.first()
} else {
None
};
let statements =
self.body[location.block].statements[location.statement_index + 1..].iter();
for stmt in statements.chain(maybe_additional_statement) {
if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind {
let (&def_id, is_generator) = match kind {
box AggregateKind::Closure(def_id, _) => (def_id, false),
@ -987,7 +986,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr {
for (captured_place, place) in
self.infcx.tcx.typeck(def_id).closure_min_captures_flattened(def_id).zip(places)
self.infcx.tcx.closure_captures(def_id).iter().zip(places)
{
match place {
Operand::Copy(place) | Operand::Move(place)

View file

@ -467,7 +467,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
err.span_suggestion_verbose(
span.shrink_to_lo(),
"consider borrowing here",
"&".to_string(),
'&',
Applicability::MaybeIncorrect,
);
}

View file

@ -385,7 +385,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
err.span_suggestion_verbose(
local_decl.source_info.span.shrink_to_lo(),
"consider changing this to be mutable",
"mut ".to_string(),
"mut ",
Applicability::MachineApplicable,
);
let tcx = self.infcx.tcx;
@ -828,7 +828,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let Some(hir::Node::Item(item)) = node else { return; };
let hir::ItemKind::Fn(.., body_id) = item.kind else { return; };
let body = self.infcx.tcx.hir().body(body_id);
let mut v = V { assign_span: span, err, ty, suggested: false };
let mut assign_span = span;
// Drop desugaring is done at MIR build so it's not in the HIR
if let Some(DesugaringKind::Replace) = span.desugaring_kind() {
assign_span.remove_mark();
}
let mut v = V { assign_span, err, ty, suggested: false };
v.visit_body(body);
if !v.suggested {
err.help(&format!(
@ -901,10 +907,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
err: &mut Diagnostic,
) {
let tables = tcx.typeck(closure_local_def_id);
let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_local_def_id);
if let Some((span, closure_kind_origin)) =
&tables.closure_kind_origins().get(closure_hir_id)
{
if let Some((span, closure_kind_origin)) = tcx.closure_kind_origin(closure_local_def_id) {
let reason = if let PlaceBase::Upvar(upvar_id) = closure_kind_origin.base {
let upvar = ty::place_to_string_for_capture(tcx, closure_kind_origin);
let root_hir_id = upvar_id.var_path.hir_id;

View file

@ -415,7 +415,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
/// ```
///
/// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
/// Here we would be invoked with `fr = 'a` and `outlived_fr = 'b`.
pub(crate) fn report_region_error(
&mut self,
fr: RegionVid,
@ -949,7 +949,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.push_span_label(*span, "this has an implicit `'static` lifetime requirement");
multi_span.push_span_label(
ident.span,
"calling this method introduces the `impl`'s 'static` requirement",
"calling this method introduces the `impl`'s `'static` requirement",
);
err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span });
err.span_suggestion_verbose(

View file

@ -6,7 +6,7 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_middle::ty::print::RegionHighlightMode;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, DefIdTree, RegionVid, Ty};
use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};

View file

@ -202,14 +202,14 @@ fn do_mir_borrowck<'tcx>(
let mut errors = error::BorrowckErrors::new(infcx.tcx);
// Gather the upvars of a closure, if any.
let tables = tcx.typeck_opt_const_arg(def);
if let Some(e) = tables.tainted_by_errors {
if let Some(e) = input_body.tainted_by_errors {
infcx.set_tainted_by_errors(e);
errors.set_tainted_by_errors(e);
}
let upvars: Vec<_> = tables
.closure_min_captures_flattened(def.did)
.map(|captured_place| {
let upvars: Vec<_> = tcx
.closure_captures(def.did)
.iter()
.map(|&captured_place| {
let capture = captured_place.info.capture_kind;
let by_ref = match capture {
ty::UpvarCapture::ByValue => false,
@ -1185,12 +1185,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
this.buffer_error(err);
}
WriteKind::StorageDeadOrDrop => this
.report_borrowed_value_does_not_live_long_enough(
location,
borrow,
place_span,
Some(kind),
),
.report_storage_dead_or_drop_of_borrowed(location, place_span, borrow),
WriteKind::Mutate => {
this.report_illegal_mutation_of_borrowed(location, place_span, borrow)
}

View file

@ -889,7 +889,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// from a universe it can't name; at present, the only way for
/// this to be true is if `scc` outlives `'static`. This is
/// actually stricter than necessary: ideally, we'd support bounds
/// like `for<'a: 'b`>` that might then allow us to approximate
/// like `for<'a: 'b>` that might then allow us to approximate
/// `'a` with `'b` and not `'static`. But it will have to do for
/// now.
fn add_incompatible_universe(&mut self, scc: ConstraintSccIndex) {

View file

@ -235,7 +235,7 @@ pub(crate) struct RegionValues<N: Idx> {
free_regions: SparseBitMatrix<N, RegionVid>,
/// Placeholders represent bound regions -- so something like `'a`
/// in for<'a> fn(&'a u32)`.
/// in `for<'a> fn(&'a u32)`.
placeholders: SparseBitMatrix<N, PlaceholderIndex>,
}

View file

@ -26,11 +26,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if !self.tcx().is_closure(mir_def_id.to_def_id()) {
return;
}
let Some(user_provided_poly_sig) =
self.tcx().typeck(mir_def_id).user_provided_sigs.get(&mir_def_id)
else {
return;
};
let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id);
// Instantiate the canonicalized variables from user-provided signature
// (e.g., the `_` in the code above) with fresh variables.

View file

@ -18,13 +18,11 @@ use rustc_errors::Diagnostic;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{BodyOwnerKind, HirId};
use rustc_hir::BodyOwnerKind;
use rustc_index::vec::{Idx, IndexVec};
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{
self, DefIdTree, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt,
};
use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
use rustc_span::Symbol;
use std::iter;
@ -231,9 +229,7 @@ impl<'tcx> UniversalRegions<'tcx> {
mir_def: ty::WithOptConstParam<LocalDefId>,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
let tcx = infcx.tcx;
let mir_hir_id = tcx.hir().local_def_id_to_hir_id(mir_def.did);
UniversalRegionsBuilder { infcx, mir_def, mir_hir_id, param_env }.build()
UniversalRegionsBuilder { infcx, mir_def, param_env }.build()
}
/// Given a reference to a closure type, extracts all the values
@ -390,7 +386,6 @@ impl<'tcx> UniversalRegions<'tcx> {
struct UniversalRegionsBuilder<'cx, 'tcx> {
infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
mir_def: ty::WithOptConstParam<LocalDefId>,
mir_hir_id: HirId,
param_env: ty::ParamEnv<'tcx>,
}
@ -560,12 +555,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
match tcx.hir().body_owner_kind(self.mir_def.did) {
BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
let defining_ty = if self.mir_def.did.to_def_id() == typeck_root_def_id {
tcx.type_of(typeck_root_def_id).subst_identity()
} else {
let tables = tcx.typeck(self.mir_def.did);
tables.node_type(self.mir_hir_id)
};
let defining_ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
debug!("defining_ty (pre-replacement): {:?}", defining_ty);
@ -594,7 +584,18 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
} else {
let ty = tcx.typeck(self.mir_def.did).node_type(self.mir_hir_id);
// FIXME this line creates a dependency between borrowck and typeck.
//
// This is required for `AscribeUserType` canonical query, which will call
// `type_of(inline_const_def_id)`. That `type_of` would inject erased lifetimes
// into borrowck, which is ICE #78174.
//
// As a workaround, inline consts have an additional generic param (`ty`
// below), so that `type_of(inline_const_def_id).substs(substs)` uses the
// proper type with NLL infer vars.
let ty = tcx
.typeck(self.mir_def.did)
.node_type(tcx.local_def_id_to_hir_id(self.mir_def.did));
let substs = InlineConstSubsts::new(
tcx,
InlineConstSubstsParts { parent_substs: identity_substs, ty },

View file

@ -53,7 +53,7 @@ pub fn expand_env<'cx>(
tts: TokenStream,
) -> Box<dyn base::MacResult + 'cx> {
let mut exprs = match get_exprs_from_tts(cx, tts) {
Some(exprs) if exprs.is_empty() => {
Some(exprs) if exprs.is_empty() || exprs.len() > 2 => {
cx.span_err(sp, "env! takes 1 or 2 arguments");
return DummyResult::any(sp);
}
@ -64,28 +64,48 @@ pub fn expand_env<'cx>(
let Some((var, _style)) = expr_to_string(cx, exprs.next().unwrap(), "expected string literal") else {
return DummyResult::any(sp);
};
let msg = match exprs.next() {
None => Symbol::intern(&format!("environment variable `{}` not defined", var)),
let custom_msg = match exprs.next() {
None => None,
Some(second) => match expr_to_string(cx, second, "expected string literal") {
None => return DummyResult::any(sp),
Some((s, _style)) => s,
Some((s, _style)) => Some(s),
},
};
if exprs.next().is_some() {
cx.span_err(sp, "env! takes 1 or 2 arguments");
return DummyResult::any(sp);
}
let sp = cx.with_def_site_ctxt(sp);
let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
let e = match value {
None => {
cx.span_err(sp, msg.as_str());
let (msg, help) = match custom_msg {
None => (
format!("environment variable `{var}` not defined at compile time"),
Some(help_for_missing_env_var(var.as_str())),
),
Some(s) => (s.to_string(), None),
};
let mut diag = cx.struct_span_err(sp, &msg);
if let Some(help) = help {
diag.help(help);
}
diag.emit();
return DummyResult::any(sp);
}
Some(value) => cx.expr_str(sp, value),
};
MacEager::expr(e)
}
fn help_for_missing_env_var(var: &str) -> String {
if var.starts_with("CARGO_")
|| var.starts_with("DEP_")
|| matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET")
{
format!(
"Cargo sets build script variables at run time. Use `std::env::var(\"{var}\")` instead"
)
} else {
format!("Use `std::env::var(\"{var}\")` to read the variable at run time")
}
}

View file

@ -21,7 +21,8 @@ mod simd;
pub(crate) use cpuid::codegen_cpuid_call;
pub(crate) use llvm::codegen_llvm_intrinsic_call;
use rustc_middle::ty::layout::HasParamEnv;
use rustc_middle::ty;
use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::SubstsRef;
use rustc_span::symbol::{kw, sym, Symbol};
@ -627,54 +628,39 @@ fn codegen_regular_intrinsic_call<'tcx>(
intrinsic_args!(fx, args => (); intrinsic);
let ty = substs.type_at(0);
let layout = fx.layout_of(ty);
if layout.abi.is_uninhabited() {
with_no_trimmed_paths!({
crate::base::codegen_panic_nounwind(
fx,
&format!("attempted to instantiate uninhabited type `{}`", layout.ty),
source_info,
)
});
return;
}
if intrinsic == sym::assert_zero_valid
&& !fx
.tcx
.permits_zero_init(fx.param_env().and(ty))
.expect("expected to have layout during codegen")
{
with_no_trimmed_paths!({
crate::base::codegen_panic_nounwind(
fx,
&format!(
"attempted to zero-initialize type `{}`, which is invalid",
layout.ty
),
source_info,
);
});
return;
}
let requirement = ValidityRequirement::from_intrinsic(intrinsic);
if intrinsic == sym::assert_mem_uninitialized_valid
&& !fx
if let Some(requirement) = requirement {
let do_panic = !fx
.tcx
.permits_uninit_init(fx.param_env().and(ty))
.expect("expected to have layout during codegen")
{
with_no_trimmed_paths!({
crate::base::codegen_panic_nounwind(
fx,
&format!(
"attempted to leave type `{}` uninitialized, which is invalid",
layout.ty
),
source_info,
)
});
return;
.check_validity_requirement((requirement, fx.param_env().and(ty)))
.expect("expect to have layout during codegen");
if do_panic {
let layout = fx.layout_of(ty);
with_no_trimmed_paths!({
crate::base::codegen_panic_nounwind(
fx,
&if layout.abi.is_uninhabited() {
format!("attempted to instantiate uninhabited type `{}`", layout.ty)
} else if requirement == ValidityRequirement::Zero {
format!(
"attempted to zero-initialize type `{}`, which is invalid",
layout.ty
)
} else {
format!(
"attempted to leave type `{}` uninitialized, which is invalid",
layout.ty
)
},
source_info,
)
});
return;
}
}
}

View file

@ -36,3 +36,5 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_ast = { path = "../rustc_ast" }
rustc_span = { path = "../rustc_span" }
tempfile = "3.2.0"
serde = { version = "1", features = [ "derive" ]}
serde_json = "1"

View file

@ -761,6 +761,7 @@ pub(crate) unsafe fn codegen(
EmitObj::None => {}
}
record_llvm_cgu_instructions_stats(&cgcx.prof, llmod);
drop(handlers);
}
@ -974,3 +975,23 @@ fn record_artifact_size(
self_profiler_ref.artifact_size(artifact_kind, artifact_name.to_string_lossy(), file_size);
}
}
fn record_llvm_cgu_instructions_stats(prof: &SelfProfilerRef, llmod: &llvm::Module) {
if !prof.enabled() {
return;
}
let raw_stats =
llvm::build_string(|s| unsafe { llvm::LLVMRustModuleInstructionStats(&llmod, s) })
.expect("cannot get module instruction stats");
#[derive(serde::Deserialize)]
struct InstructionsStats {
module: String,
total: u64,
}
let InstructionsStats { module, total } =
serde_json::from_str(&raw_stats).expect("cannot parse llvm cgu instructions stats");
prof.artifact_size("cgu_instructions", module, total);
}

View file

@ -10,6 +10,7 @@ use crate::value::Value;
use rustc_ast::Mutability;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::DefId;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
@ -252,8 +253,13 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
_ => self.static_addr_of(init, alloc.align, None),
};
if !self.sess().fewer_names() {
llvm::set_value_name(value, format!("{:?}", alloc_id).as_bytes());
if !self.sess().fewer_names() && llvm::get_value_name(value).is_empty() {
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
alloc.hash_stable(&mut hcx, &mut hasher);
hasher.finish::<u128>()
});
llvm::set_value_name(value, format!("alloc_{hash:032x}").as_bytes());
}
(value, AddressSpace::DATA)
}

View file

@ -5,7 +5,7 @@ use super::CodegenUnitDebugContext;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
use rustc_middle::ty::{self, DefIdTree, Ty};
use rustc_middle::ty::{self, Ty};
use trace;
use crate::common::CodegenCx;

View file

@ -1814,8 +1814,6 @@ extern "C" {
/// Creates a legacy pass manager -- only used for final codegen.
pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>;
pub fn LLVMInitializePasses();
pub fn LLVMTimeTraceProfilerInitialize();
pub fn LLVMTimeTraceProfilerFinishThread();
@ -2410,6 +2408,8 @@ extern "C" {
pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize;
pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer);
pub fn LLVMRustModuleCost(M: &Module) -> u64;
#[allow(improper_ctypes)]
pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString);
pub fn LLVMRustThinLTOBufferCreate(M: &Module, is_thin: bool) -> &'static mut ThinLTOBuffer;
pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);

View file

@ -120,8 +120,6 @@ unsafe fn configure_llvm(sess: &Session) {
llvm::LLVMTimeTraceProfilerInitialize();
}
llvm::LLVMInitializePasses();
rustc_llvm::initialize_available_targets();
llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());

View file

@ -306,7 +306,13 @@ pub fn create_compressed_metadata_file(
symbol_name: &str,
) -> Vec<u8> {
let mut compressed = rustc_metadata::METADATA_HEADER.to_vec();
// Our length will be backfilled once we're done writing
compressed.write_all(&[0; 4]).unwrap();
FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap();
let meta_len = rustc_metadata::METADATA_HEADER.len();
let data_len = (compressed.len() - meta_len - 4) as u32;
compressed[meta_len..meta_len + 4].copy_from_slice(&data_len.to_be_bytes());
let Some(mut file) = create_object_file(sess) else {
return compressed.to_vec();
};

View file

@ -11,7 +11,7 @@ use rustc_middle::middle::exported_symbols::{
use rustc_middle::ty::query::{ExternProviders, Providers};
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::Instance;
use rustc_middle::ty::{self, DefIdTree, SymbolName, TyCtxt};
use rustc_middle::ty::{self, SymbolName, TyCtxt};
use rustc_session::config::{CrateType, OomStrategy};
use rustc_target::spec::SanitizerSet;

View file

@ -8,7 +8,7 @@ use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self as ty, DefIdTree, TyCtxt};
use rustc_middle::ty::{self as ty, TyCtxt};
use rustc_session::{lint, parse::feature_err};
use rustc_span::{sym, Span};
use rustc_target::spec::{abi, SanitizerSet};

View file

@ -14,7 +14,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::lang_items::LangItem;
use rustc_index::vec::Idx;
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
use rustc_session::config::OptLevel;
@ -655,41 +655,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// Emit a panic or a no-op for `assert_*` intrinsics.
// These are intrinsics that compile to panics so that we can get a message
// which mentions the offending type, even from a const context.
#[derive(Debug, PartialEq)]
enum AssertIntrinsic {
Inhabited,
ZeroValid,
MemUninitializedValid,
}
let panic_intrinsic = intrinsic.and_then(|i| match i {
sym::assert_inhabited => Some(AssertIntrinsic::Inhabited),
sym::assert_zero_valid => Some(AssertIntrinsic::ZeroValid),
sym::assert_mem_uninitialized_valid => Some(AssertIntrinsic::MemUninitializedValid),
_ => None,
});
if let Some(intrinsic) = panic_intrinsic {
use AssertIntrinsic::*;
let panic_intrinsic = intrinsic.and_then(|s| ValidityRequirement::from_intrinsic(s));
if let Some(requirement) = panic_intrinsic {
let ty = instance.unwrap().substs.type_at(0);
let do_panic = !bx
.tcx()
.check_validity_requirement((requirement, bx.param_env().and(ty)))
.expect("expect to have layout during codegen");
let layout = bx.layout_of(ty);
let do_panic = match intrinsic {
Inhabited => layout.abi.is_uninhabited(),
ZeroValid => !bx
.tcx()
.permits_zero_init(bx.param_env().and(ty))
.expect("expected to have layout during codegen"),
MemUninitializedValid => !bx
.tcx()
.permits_uninit_init(bx.param_env().and(ty))
.expect("expected to have layout during codegen"),
};
Some(if do_panic {
let msg_str = with_no_visible_paths!({
with_no_trimmed_paths!({
if layout.abi.is_uninhabited() {
// Use this error even for the other intrinsics as it is more precise.
format!("attempted to instantiate uninhabited type `{}`", ty)
} else if intrinsic == ZeroValid {
} else if requirement == ValidityRequirement::Zero {
format!("attempted to zero-initialize type `{}`, which is invalid", ty)
} else {
format!(

View file

@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{DefIdTree, TyCtxt};
use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
use rustc_session::Session;
use rustc_span::symbol::sym;
@ -185,7 +185,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("avx512vpopcntdq", Some(sym::avx512_target_feature)),
("bmi1", None),
("bmi2", None),
("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
("cmpxchg16b", None),
("ermsb", Some(sym::ermsb_target_feature)),
("f16c", None),
("fma", None),
@ -394,7 +394,6 @@ pub fn from_target_feature(
Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,

View file

@ -2,7 +2,7 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{DefIdTree, TyCtxt};
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::Symbol;
/// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it

View file

@ -11,7 +11,7 @@ use rustc_middle::mir::{
BinOp, NonDivergingIntrinsic,
};
use rustc_middle::ty;
use rustc_middle::ty::layout::LayoutOf as _;
use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
@ -418,54 +418,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
| sym::assert_zero_valid
| sym::assert_mem_uninitialized_valid => {
let ty = instance.substs.type_at(0);
let layout = self.layout_of(ty)?;
let requirement = ValidityRequirement::from_intrinsic(intrinsic_name).unwrap();
// For *all* intrinsics we first check `is_uninhabited` to give a more specific
// error message.
if layout.abi.is_uninhabited() {
// The run-time intrinsic panics just to get a good backtrace; here we abort
// since there is no problem showing a backtrace even for aborts.
M::abort(
self,
format!(
let should_panic = !self
.tcx
.check_validity_requirement((requirement, self.param_env.and(ty)))
.map_err(|_| err_inval!(TooGeneric))?;
if should_panic {
let layout = self.layout_of(ty)?;
let msg = match requirement {
// For *all* intrinsics we first check `is_uninhabited` to give a more specific
// error message.
_ if layout.abi.is_uninhabited() => format!(
"aborted execution: attempted to instantiate uninhabited type `{}`",
ty
),
)?;
}
ValidityRequirement::Inhabited => bug!("handled earlier"),
ValidityRequirement::Zero => format!(
"aborted execution: attempted to zero-initialize type `{}`, which is invalid",
ty
),
ValidityRequirement::UninitMitigated0x01Fill => format!(
"aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
ty
),
ValidityRequirement::Uninit => bug!("assert_uninit_valid doesn't exist"),
};
if intrinsic_name == sym::assert_zero_valid {
let should_panic = !self
.tcx
.permits_zero_init(self.param_env.and(ty))
.map_err(|_| err_inval!(TooGeneric))?;
if should_panic {
M::abort(
self,
format!(
"aborted execution: attempted to zero-initialize type `{}`, which is invalid",
ty
),
)?;
}
}
if intrinsic_name == sym::assert_mem_uninitialized_valid {
let should_panic = !self
.tcx
.permits_uninit_init(self.param_env.and(ty))
.map_err(|_| err_inval!(TooGeneric))?;
if should_panic {
M::abort(
self,
format!(
"aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
ty
),
)?;
}
M::abort(self, msg)?;
}
}
sym::simd_insert => {
@ -476,7 +458,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert_eq!(input_len, dest_len, "Return vector length must match input length");
assert!(
index < dest_len,
"Index `{}` must be in bounds of vector with length {}`",
"Index `{}` must be in bounds of vector with length {}",
index,
dest_len
);
@ -496,7 +478,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let (input, input_len) = self.operand_to_simd(&args[0])?;
assert!(
index < input_len,
"index `{}` must be in bounds of vector with length `{}`",
"index `{}` must be in bounds of vector with length {}",
index,
input_len
);

View file

@ -16,8 +16,8 @@ use rustc_target::spec::abi::Abi as CallAbi;
use crate::const_eval::CheckAlignment;
use super::{
AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx,
InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
};
/// Data returned by Machine::stack_pop,
@ -105,10 +105,16 @@ pub trait Machine<'mir, 'tcx>: Sized {
/// Extra data stored in every allocation.
type AllocExtra: Debug + Clone + 'static;
/// Type for the bytes of the allocation.
type Bytes: AllocBytes + 'static;
/// Memory's allocation map
type MemoryMap: AllocMap<
AllocId,
(MemoryKind<Self::MemoryKind>, Allocation<Self::Provenance, Self::AllocExtra>),
(
MemoryKind<Self::MemoryKind>,
Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>,
),
> + Default
+ Clone;
@ -338,7 +344,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
id: AllocId,
alloc: Cow<'b, Allocation>,
kind: Option<MemoryKind<Self::MemoryKind>>,
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra>>>;
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>;
fn eval_inline_asm(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
@ -459,6 +465,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
type AllocExtra = ();
type FrameExtra = ();
type Bytes = Box<[u8]>;
#[inline(always)]
fn use_addr_for_alignment_check(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {

View file

@ -21,8 +21,9 @@ use rustc_target::abi::{Align, HasDataLayout, Size};
use crate::const_eval::CheckAlignment;
use super::{
alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx,
InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar,
alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg,
GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance,
Scalar,
};
#[derive(Debug, PartialEq, Copy, Clone)]
@ -114,16 +115,16 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
/// A reference to some allocation that was already bounds-checked for the given region
/// and had the on-access machine hooks run.
#[derive(Copy, Clone)]
pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra> {
alloc: &'a Allocation<Prov, Extra>,
pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
alloc: &'a Allocation<Prov, Extra, Bytes>,
range: AllocRange,
tcx: TyCtxt<'tcx>,
alloc_id: AllocId,
}
/// A reference to some allocation that was already bounds-checked for the given region
/// and had the on-access machine hooks run.
pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra> {
alloc: &'a mut Allocation<Prov, Extra>,
pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
alloc: &'a mut Allocation<Prov, Extra, Bytes>,
range: AllocRange,
tcx: TyCtxt<'tcx>,
alloc_id: AllocId,
@ -483,7 +484,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&self,
id: AllocId,
is_write: bool,
) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::Provenance, M::AllocExtra>>> {
) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::Provenance, M::AllocExtra, M::Bytes>>> {
let (alloc, def_id) = match self.tcx.try_get_global_alloc(id) {
Some(GlobalAlloc::Memory(mem)) => {
// Memory of a constant or promoted or anonymous memory referenced by a static.
@ -526,6 +527,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
)
}
/// Get the base address for the bytes in an `Allocation` specified by the
/// `AllocID` passed in; error if no such allocation exists.
///
/// It is up to the caller to take sufficient care when using this address:
/// there could be provenance or uninit memory in there, and other memory
/// accesses could invalidate the exposed pointer.
pub fn alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, *const u8> {
let alloc = self.get_alloc_raw(id)?;
Ok(alloc.base_addr())
}
/// Gives raw access to the `Allocation`, without bounds or alignment checks.
/// The caller is responsible for calling the access hooks!
///
@ -533,7 +545,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
fn get_alloc_raw(
&self,
id: AllocId,
) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra>> {
) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra, M::Bytes>> {
// The error type of the inner closure here is somewhat funny. We have two
// ways of "erroring": An actual error, or because we got a reference from
// `get_global_alloc` that we can actually use directly without inserting anything anywhere.
@ -569,7 +581,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ptr: Pointer<Option<M::Provenance>>,
size: Size,
align: Align,
) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
{
let ptr_and_alloc = self.check_and_deref_ptr(
ptr,
size,
@ -612,7 +625,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
fn get_alloc_raw_mut(
&mut self,
id: AllocId,
) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra>, &mut M)> {
) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra, M::Bytes>, &mut M)> {
// We have "NLL problem case #3" here, which cannot be worked around without loss of
// efficiency even for the common case where the key is in the map.
// <https://rust-lang.github.io/rfcs/2094-nll.html#problem-case-3-conditional-control-flow-across-functions>
@ -641,7 +654,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ptr: Pointer<Option<M::Provenance>>,
size: Size,
align: Align,
) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
{
let parts = self.get_ptr_access(ptr, size, align)?;
if let Some((alloc_id, offset, prov)) = parts {
let tcx = *self.tcx;
@ -840,11 +854,11 @@ pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Cannot be a closure because it is generic in `Prov`, `Extra`.
fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra>(
fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
fmt: &mut std::fmt::Formatter<'_>,
tcx: TyCtxt<'tcx>,
allocs_to_print: &mut VecDeque<AllocId>,
alloc: &Allocation<Prov, Extra>,
alloc: &Allocation<Prov, Extra, Bytes>,
) -> std::fmt::Result {
for alloc_id in alloc.provenance().provenances().filter_map(|prov| prov.get_alloc_id())
{
@ -912,7 +926,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a,
}
/// Reading and writing.
impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> {
impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes>
AllocRefMut<'a, 'tcx, Prov, Extra, Bytes>
{
/// `range` is relative to this allocation reference, not the base of the allocation.
pub fn write_scalar(&mut self, range: AllocRange, val: Scalar<Prov>) -> InterpResult<'tcx> {
let range = self.range.subrange(range);
@ -937,7 +953,7 @@ impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> {
}
}
impl<'tcx, 'a, Prov: Provenance, Extra> AllocRef<'a, 'tcx, Prov, Extra> {
impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> {
/// `range` is relative to this allocation reference, not the base of the allocation.
pub fn read_scalar(
&self,

View file

@ -353,7 +353,8 @@ where
pub(super) fn get_place_alloc(
&self,
place: &MPlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra>>> {
) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
{
assert!(place.layout.is_sized());
assert!(!place.meta.has_meta());
let size = place.layout.size;
@ -364,7 +365,8 @@ where
pub(super) fn get_place_alloc_mut(
&mut self,
place: &MPlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra>>> {
) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
{
assert!(place.layout.is_sized());
assert!(!place.meta.has_meta());
let size = place.layout.size;

View file

@ -240,10 +240,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// FIXME this should be more descriptive i.e. CapturePlace instead of CapturedVar
// https://github.com/rust-lang/project-rfc-2229/issues/46
if let Some(local_def_id) = def_id.as_local() {
let tables = self.ecx.tcx.typeck(local_def_id);
if let Some(captured_place) =
tables.closure_min_captures_flattened(local_def_id).nth(field)
{
let captures = self.ecx.tcx.closure_captures(local_def_id);
if let Some(captured_place) = captures.get(field) {
// Sometimes the index is beyond the number of upvars (seen
// for a generator).
let var_hir_id = captured_place.get_root_variable();

View file

@ -38,7 +38,6 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_macros::fluent_messages;
use rustc_middle::ty;
use rustc_middle::ty::query::Providers;
use rustc_target::abi::InitKind;
fluent_messages! { "../locales/en-US.ftl" }
@ -62,9 +61,7 @@ pub fn provide(providers: &mut Providers) {
let (param_env, value) = param_env_and_value.into_parts();
const_eval::deref_mir_constant(tcx, param_env, value)
};
providers.permits_uninit_init = |tcx, param_env_and_ty| {
util::might_permit_raw_init(tcx, param_env_and_ty, InitKind::UninitMitigated0x01Fill)
providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
};
providers.permits_zero_init =
|tcx, param_env_and_ty| util::might_permit_raw_init(tcx, param_env_and_ty, InitKind::Zero);
}

View file

@ -332,7 +332,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
fn check_static(&mut self, def_id: DefId, span: Span) {
if self.tcx.is_thread_local_static(def_id) {
self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef");
self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
}
self.check_op_spanned(ops::StaticAccess, span)
}

View file

@ -12,9 +12,7 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
use rustc_middle::mir;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{
suggest_constraining_type_param, Adt, Closure, DefIdTree, FnDef, FnPtr, Param, Ty,
};
use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty};
use rustc_middle::ty::{Binder, TraitRef};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;

View file

@ -755,8 +755,26 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail(location, format!("explicit `{:?}` is forbidden", kind));
}
}
StatementKind::StorageLive(..)
| StatementKind::StorageDead(..)
StatementKind::StorageLive(local) => {
// We check that the local is not live when entering a `StorageLive` for it.
// Technically, violating this restriction is only UB and not actually indicative
// of not well-formed MIR. This means that an optimization which turns MIR that
// already has UB into MIR that fails this check is not necessarily wrong. However,
// we have no such optimizations at the moment, and so we include this check anyway
// to help us catch bugs. If you happen to write an optimization that might cause
// this to incorrectly fire, feel free to remove this check.
if self.reachable_blocks.contains(location.block) {
self.storage_liveness.seek_before_primary_effect(location);
let locals_with_storage = self.storage_liveness.get();
if locals_with_storage.contains(*local) {
self.fail(
location,
format!("StorageLive({local:?}) which already has storage here"),
);
}
}
}
StatementKind::StorageDead(_)
| StatementKind::Coverage(_)
| StatementKind::ConstEvalCounter
| StatementKind::Nop => {}

View file

@ -1,7 +1,7 @@
use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout};
use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement};
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_session::Limit;
use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants};
use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
use crate::const_eval::{CheckAlignment, CompileTimeInterpreter};
use crate::interpret::{InterpCx, MemoryKind, OpTy};
@ -18,16 +18,23 @@ use crate::interpret::{InterpCx, MemoryKind, OpTy};
/// Rust UB as long as there is no risk of miscompilations. The `strict_init_checks` can be set to
/// do a full check against Rust UB instead (in which case we will also ignore the 0x01-filling and
/// to the full uninit check).
pub fn might_permit_raw_init<'tcx>(
pub fn check_validity_requirement<'tcx>(
tcx: TyCtxt<'tcx>,
kind: ValidityRequirement,
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
kind: InitKind,
) -> Result<bool, LayoutError<'tcx>> {
if tcx.sess.opts.unstable_opts.strict_init_checks {
might_permit_raw_init_strict(tcx.layout_of(param_env_and_ty)?, tcx, kind)
let layout = tcx.layout_of(param_env_and_ty)?;
// There is nothing strict or lax about inhabitedness.
if kind == ValidityRequirement::Inhabited {
return Ok(!layout.abi.is_uninhabited());
}
if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
might_permit_raw_init_strict(layout, tcx, kind)
} else {
let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
might_permit_raw_init_lax(tcx.layout_of(param_env_and_ty)?, &layout_cx, kind)
might_permit_raw_init_lax(layout, &layout_cx, kind)
}
}
@ -36,7 +43,7 @@ pub fn might_permit_raw_init<'tcx>(
fn might_permit_raw_init_strict<'tcx>(
ty: TyAndLayout<'tcx>,
tcx: TyCtxt<'tcx>,
kind: InitKind,
kind: ValidityRequirement,
) -> Result<bool, LayoutError<'tcx>> {
let machine = CompileTimeInterpreter::new(
Limit::new(0),
@ -50,7 +57,7 @@ fn might_permit_raw_init_strict<'tcx>(
.allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
.expect("OOM: failed to allocate for uninit check");
if kind == InitKind::Zero {
if kind == ValidityRequirement::Zero {
cx.write_bytes_ptr(
allocated.ptr,
std::iter::repeat(0_u8).take(ty.layout.size().bytes_usize()),
@ -72,15 +79,18 @@ fn might_permit_raw_init_strict<'tcx>(
fn might_permit_raw_init_lax<'tcx>(
this: TyAndLayout<'tcx>,
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
init_kind: InitKind,
init_kind: ValidityRequirement,
) -> Result<bool, LayoutError<'tcx>> {
let scalar_allows_raw_init = move |s: Scalar| -> bool {
match init_kind {
InitKind::Zero => {
ValidityRequirement::Inhabited => {
bug!("ValidityRequirement::Inhabited should have been handled above")
}
ValidityRequirement::Zero => {
// The range must contain 0.
s.valid_range(cx).contains(0)
}
InitKind::UninitMitigated0x01Fill => {
ValidityRequirement::UninitMitigated0x01Fill => {
// The range must include an 0x01-filled buffer.
let mut val: u128 = 0x01;
for _ in 1..s.size(cx).bytes() {
@ -89,6 +99,9 @@ fn might_permit_raw_init_lax<'tcx>(
}
s.valid_range(cx).contains(val)
}
ValidityRequirement::Uninit => {
bug!("ValidityRequirement::Uninit should have been handled above")
}
}
};

View file

@ -1,14 +1,14 @@
mod alignment;
mod call_kind;
mod check_validity_requirement;
pub mod collect_writes;
mod compare_types;
mod find_self_call;
mod might_permit_raw_init;
mod type_name;
pub use self::alignment::is_disaligned;
pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind};
pub use self::check_validity_requirement::check_validity_requirement;
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
pub use self::find_self_call::find_self_call;
pub use self::might_permit_raw_init::might_permit_raw_init;
pub use self::type_name::type_name;

View file

@ -9,7 +9,7 @@ edition = "2021"
arrayvec = { version = "0.7", default-features = false }
bitflags = "1.2.1"
cfg-if = "1.0"
ena = "0.14"
ena = "0.14.1"
indexmap = { version = "1.9.1" }
jobserver_crate = { version = "0.1.13", package = "jobserver" }
libc = "0.2"

View file

@ -426,6 +426,7 @@ impl<O: ForestObligation> ObligationForest<O> {
// nodes. Therefore we use a `while` loop.
let mut index = 0;
while let Some(node) = self.nodes.get_mut(index) {
// This test is extremely hot.
if node.state.get() != NodeState::Pending
|| !processor.needs_process_obligation(&node.obligation)
{
@ -439,6 +440,7 @@ impl<O: ForestObligation> ObligationForest<O> {
// out of sync with `nodes`. It's not very common, but it does
// happen, and code in `compress` has to allow for it.
// This code is much less hot.
match processor.process_obligation(&mut node.obligation) {
ProcessResult::Unchanged => {
// No change in state.

View file

@ -100,6 +100,11 @@ impl<I: Idx, K: Ord, V> SortedIndexMultiMap<I, K, V> {
(k == &key).then_some((i, v))
})
}
#[inline]
pub fn contains_key(&self, key: K) -> bool {
self.get_by_key(key).next().is_some()
}
}
impl<I: Idx, K: Eq, V: Eq> Eq for SortedIndexMultiMap<I, K, V> {}

View file

@ -17,6 +17,10 @@ fn test_sorted_index_multi_map() {
assert_eq!(set.get_by_key(3).copied().collect::<Vec<_>>(), vec![0]);
assert!(set.get_by_key(4).next().is_none());
// `contains_key` works
assert!(set.contains_key(3));
assert!(!set.contains_key(4));
// `get_by_key` returns items in insertion order.
let twos: Vec<_> = set.get_by_key_enumerated(2).collect();
let idxs: Vec<usize> = twos.iter().map(|(i, _)| *i).collect();

View file

@ -150,7 +150,7 @@ fn test_isize_compression() {
let hash_b = hash(&(b as isize, a as isize));
assert_ne!(
hash_a, hash_b,
"The hash stayed the same when permuting values `{a}` and `{b}!",
"The hash stayed the same when permuting values `{a}` and `{b}`!",
);
}

View file

@ -1895,7 +1895,7 @@ impl EmitterWriter {
self.draw_code_line(
&mut buffer,
&mut row_num,
&Vec::new(),
&[],
p + line_start,
l,
show_code_change,
@ -1919,7 +1919,7 @@ impl EmitterWriter {
self.draw_code_line(
&mut buffer,
&mut row_num,
&Vec::new(),
&[],
p + line_start,
l,
show_code_change,
@ -1936,7 +1936,7 @@ impl EmitterWriter {
self.draw_code_line(
&mut buffer,
&mut row_num,
&Vec::new(),
&[],
p + line_start,
l,
show_code_change,
@ -1951,7 +1951,7 @@ impl EmitterWriter {
self.draw_code_line(
&mut buffer,
&mut row_num,
highlight_parts,
&highlight_parts,
line_pos + line_start,
line,
show_code_change,
@ -2176,7 +2176,7 @@ impl EmitterWriter {
&self,
buffer: &mut StyledBuffer,
row_num: &mut usize,
highlight_parts: &Vec<SubstitutionHighlight>,
highlight_parts: &[SubstitutionHighlight],
line_num: usize,
line_to_add: &str,
show_code_change: DisplaySuggestion,

View file

@ -331,7 +331,7 @@ impl CodeSuggestion {
});
buf.push_str(&part.snippet);
let cur_hi = sm.lookup_char_pos(part.span.hi());
if prev_hi.line == cur_lo.line && cur_hi.line == cur_lo.line {
if cur_hi.line == cur_lo.line {
// Account for the difference between the width of the current code and the
// snippet being suggested, so that the *later* suggestions are correctly
// aligned on the screen.

View file

@ -133,3 +133,6 @@ expand_trace_macro = trace_macro
expand_proc_macro_panicked =
proc macro panicked
.help = message: {$message}
expand_proc_macro_derive_tokens =
proc-macro derive produced unparseable tokens

View file

@ -390,3 +390,10 @@ pub(crate) struct ProcMacroPanicked {
pub(crate) struct ProcMacroPanickedHelp {
pub message: String,
}
#[derive(Diagnostic)]
#[diag(expand_proc_macro_derive_tokens)]
pub struct ProcMacroDeriveTokens {
#[primary_span]
pub span: Span,
}

View file

@ -282,7 +282,7 @@ pub(super) fn transcribe<'a>(
}
// There should be no meta-var declarations in the invocation of a macro.
mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl"),
mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl`"),
}
}
}

View file

@ -176,7 +176,7 @@ impl MultiItemModifier for DeriveProcMacro {
// fail if there have been errors emitted
if ecx.sess.parse_sess.span_diagnostic.err_count() > error_count_before {
ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit();
ecx.sess.emit_err(errors::ProcMacroDeriveTokens { span });
}
ExpandResult::Ready(items)

View file

@ -43,7 +43,6 @@ pub(crate) fn string_to_stream(source_str: String) -> TokenStream {
ps.source_map().new_source_file(PathBuf::from("bogofile").into(), source_str),
None,
)
.0
}
/// Parses a string, returns a crate.

View file

@ -90,6 +90,8 @@ declare_features! (
(accepted, clone_closures, "1.26.0", Some(44490), None),
/// Allows coercing non capturing closures to function pointers.
(accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None),
/// Allows using `cmpxchg16b` from `core::arch::x86_64`.
(accepted, cmpxchg16b_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None),
/// Allows usage of the `compile_error!` macro.
(accepted, compile_error, "1.20.0", Some(40872), None),
/// Allows `impl Trait` in function return types.

View file

@ -256,7 +256,6 @@ declare_features! (
(active, arm_target_feature, "1.27.0", Some(44839), None),
(active, avx512_target_feature, "1.27.0", Some(44839), None),
(active, bpf_target_feature, "1.54.0", Some(44839), None),
(active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None),
(active, ermsb_target_feature, "1.49.0", Some(44839), None),
(active, hexagon_target_feature, "1.27.0", Some(44839), None),
(active, mips_target_feature, "1.27.0", Some(44839), None),
@ -317,8 +316,6 @@ declare_features! (
(active, c_unwind, "1.52.0", Some(74990), None),
/// Allows using C-variadics.
(active, c_variadic, "1.34.0", Some(44930), None),
/// Allows capturing disjoint fields in a closure/generator (RFC 2229).
(incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None),
/// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
(active, cfg_sanitize, "1.41.0", Some(39699), None),
/// Allows `cfg(target_abi = "...")`.

View file

@ -52,6 +52,8 @@ declare_features! (
(removed, allow_fail, "1.19.0", Some(46488), None, Some("removed due to no clear use cases")),
(removed, await_macro, "1.38.0", Some(50547), None,
Some("subsumed by `.await` syntax")),
/// Allows capturing disjoint fields in a closure/generator (RFC 2229).
(removed, capture_disjoint_fields, "1.49.0", Some(53488), None, Some("stabilized in Rust 2021")),
/// Allows comparing raw pointers during const eval.
(removed, const_compare_raw_pointers, "1.46.0", Some(53020), None,
Some("cannot be allowed in const eval in any meaningful way")),

View file

@ -498,6 +498,7 @@ pub struct GenericParam<'hir> {
pub pure_wrt_drop: bool,
pub kind: GenericParamKind<'hir>,
pub colon_span: Option<Span>,
pub source: GenericParamSource,
}
impl<'hir> GenericParam<'hir> {
@ -516,6 +517,20 @@ impl<'hir> GenericParam<'hir> {
}
}
/// Records where the generic parameter originated from.
///
/// This can either be from an item's generics, in which case it's typically
/// early-bound (but can be a late-bound lifetime in functions, for example),
/// or from a `for<...>` binder, in which case it's late-bound (and notably,
/// does not show up in the parent item's generics).
#[derive(Debug, HashStable_Generic, PartialEq, Eq, Copy, Clone)]
pub enum GenericParamSource {
// Early or late-bound parameters defined on an item
Generics,
// Late-bound parameters defined via a `for<...>`
Binder,
}
#[derive(Default)]
pub struct GenericParamCount {
pub lifetimes: usize,

View file

@ -62,14 +62,6 @@ hir_analysis_manual_implementation =
hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
hir_analysis_unused_extern_crate =
unused extern crate
.suggestion = remove it
hir_analysis_extern_crate_not_idiomatic =
`extern crate` is not idiomatic in the new edition
.suggestion = convert it to a `{$msg_code}`
hir_analysis_trait_object_declared_with_no_traits =
at least one trait is required for an object type
.alias_span = this alias does not contain a trait
@ -155,3 +147,11 @@ hir_analysis_main_function_generic_parameters = `main` function is not allowed t
hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
.label = C-variadic function must have a compatible calling convention
hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
cannot capture late-bound type parameter in a constant
.label = parameter defined here
hir_analysis_cannot_capture_late_bound_const_in_anon_const =
cannot capture late-bound const parameter in a constant
.label = parameter defined here

View file

@ -35,7 +35,7 @@ use rustc_middle::middle::stability::AllowUnstable;
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
use rustc_middle::ty::DynKind;
use rustc_middle::ty::GenericParamDefKind;
use rustc_middle::ty::{self, Const, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
@ -50,6 +50,7 @@ use rustc_trait_selection::traits::{self, astconv_object_safety_violations, Obli
use smallvec::{smallvec, SmallVec};
use std::collections::BTreeSet;
use std::fmt::Display;
use std::slice;
#[derive(Debug)]
@ -1095,11 +1096,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// those that do.
self.one_bound_for_assoc_type(
|| traits::supertraits(tcx, trait_ref),
|| trait_ref.print_only_trait_path().to_string(),
trait_ref.print_only_trait_path(),
binding.item_name,
path_span,
|| match binding.kind {
ConvertedBindingKind::Equality(ty) => Some(ty.to_string()),
match binding.kind {
ConvertedBindingKind::Equality(term) => Some(term),
_ => None,
},
)?
@ -1789,10 +1790,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
assoc_name,
)
},
|| param_name.to_string(),
param_name,
assoc_name,
span,
|| None,
None,
)
}
@ -1802,10 +1803,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
fn one_bound_for_assoc_type<I>(
&self,
all_candidates: impl Fn() -> I,
ty_param_name: impl Fn() -> String,
ty_param_name: impl Display,
assoc_name: Ident,
span: Span,
is_equality: impl Fn() -> Option<String>,
is_equality: Option<ty::Term<'tcx>>,
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed>
where
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
@ -1821,7 +1822,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
(None, None) => {
let reported = self.complain_about_assoc_type_not_found(
all_candidates,
&ty_param_name(),
&ty_param_name.to_string(),
assoc_name,
span,
);
@ -1833,7 +1834,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(bound2) = next_cand {
debug!(?bound2);
let is_equality = is_equality();
let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates);
let mut err = if is_equality.is_some() {
// More specific Error Index entry.
@ -1843,7 +1843,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
E0222,
"ambiguous associated type `{}` in bounds of `{}`",
assoc_name,
ty_param_name()
ty_param_name
)
} else {
struct_span_err!(
@ -1852,7 +1852,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
E0221,
"ambiguous associated type `{}` in bounds of `{}`",
assoc_name,
ty_param_name()
ty_param_name
)
};
err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
@ -1886,18 +1886,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.span_suggestion_verbose(
span.with_hi(assoc_name.span.lo()),
"use fully qualified syntax to disambiguate",
format!(
"<{} as {}>::",
ty_param_name(),
bound.print_only_trait_path(),
),
format!("<{} as {}>::", ty_param_name, bound.print_only_trait_path()),
Applicability::MaybeIncorrect,
);
}
} else {
err.note(&format!(
"associated type `{}` could derive from `{}`",
ty_param_name(),
ty_param_name,
bound.print_only_trait_path(),
));
}
@ -1906,7 +1902,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.help(&format!(
"consider introducing a new type parameter `T` and adding `where` constraints:\
\n where\n T: {},\n{}",
ty_param_name(),
ty_param_name,
where_bounds.join(",\n"),
));
}
@ -2070,10 +2066,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.one_bound_for_assoc_type(
|| traits::supertraits(tcx, ty::Binder::dummy(trait_ref.subst_identity())),
|| "Self".to_string(),
kw::SelfUpper,
assoc_ident,
span,
|| None,
None,
)?
}
(
@ -2403,8 +2399,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
infcx
.can_eq(
ty::ParamEnv::empty(),
tcx.erase_regions(impl_.self_ty()),
tcx.erase_regions(qself_ty),
impl_.self_ty(),
// Must fold past escaping bound vars too,
// since we have those at this point in astconv.
tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased),
)
})
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative

View file

@ -22,8 +22,7 @@ use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{
self, AdtDef, DefIdTree, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt,
self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_span::symbol::sym;
@ -792,8 +791,10 @@ fn check_impl_items_against_trait<'tcx>(
trait_def.must_implement_one_of.as_deref();
for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) {
let is_implemented = ancestors
.leaf_def(tcx, trait_item_id)
let leaf_def = ancestors.leaf_def(tcx, trait_item_id);
let is_implemented = leaf_def
.as_ref()
.map_or(false, |node_item| node_item.item.defaultness(tcx).has_value());
if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
@ -801,8 +802,8 @@ fn check_impl_items_against_trait<'tcx>(
}
// true if this item is specifically implemented in this impl
let is_implemented_here = ancestors
.leaf_def(tcx, trait_item_id)
let is_implemented_here = leaf_def
.as_ref()
.map_or(false, |node_item| !node_item.defining_node.is_from_trait());
if !is_implemented_here {
@ -831,6 +832,36 @@ fn check_impl_items_against_trait<'tcx>(
}
}
}
if let Some(leaf_def) = &leaf_def
&& !leaf_def.is_final()
&& let def_id = leaf_def.item.def_id
&& tcx.impl_method_has_trait_impl_trait_tys(def_id)
{
let def_kind = tcx.def_kind(def_id);
let descr = tcx.def_kind_descr(def_kind, def_id);
let (msg, feature) = if tcx.asyncness(def_id).is_async() {
(
format!("async {descr} in trait cannot be specialized"),
sym::async_fn_in_trait,
)
} else {
(
format!(
"{descr} with return-position `impl Trait` in trait cannot be specialized"
),
sym::return_position_impl_trait_in_trait,
)
};
tcx.sess
.struct_span_err(tcx.def_span(def_id), msg)
.note(format!(
"specialization behaves in inconsistent and \
surprising ways with `#![feature({feature})]`, \
and for now is disallowed"
))
.emit();
}
}
if !missing_items.is_empty() {

View file

@ -16,8 +16,7 @@ use rustc_infer::traits::util;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::util::ExplicitSelf;
use rustc_middle::ty::{
self, DefIdTree, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt,
self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
use rustc_span::Span;
@ -648,6 +647,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
)
.fold_with(&mut collector);
debug_assert_ne!(
collector.types.len(),
0,
"expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`"
);
let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig);
trait_sig.error_reported()?;
let trait_return_ty = trait_sig.output();
@ -1866,7 +1872,7 @@ pub(super) fn check_type_bounds<'tcx>(
// type Bar<C> =...
// }
//
// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>
// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
// - `impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
// - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
// the *trait* with the generic associated type parameters (as bound vars).

View file

@ -1,12 +1,8 @@
use crate::errors::{ExternCrateNotIdiomatic, UnusedExternCrate};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::unord::UnordSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint;
use rustc_span::{Span, Symbol};
pub fn check_crate(tcx: TyCtxt<'_>) {
let mut used_trait_imports: UnordSet<LocalDefId> = Default::default();
@ -43,131 +39,4 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|lint| lint,
);
}
unused_crates_lint(tcx);
}
fn unused_crates_lint(tcx: TyCtxt<'_>) {
let lint = lint::builtin::UNUSED_EXTERN_CRATES;
// Collect first the crates that are completely unused. These we
// can always suggest removing (no matter which edition we are
// in).
let unused_extern_crates: FxHashMap<LocalDefId, Span> = tcx
.maybe_unused_extern_crates(())
.iter()
.filter(|&&(def_id, _)| {
tcx.extern_mod_stmt_cnum(def_id).map_or(true, |cnum| {
!tcx.is_compiler_builtins(cnum)
&& !tcx.is_panic_runtime(cnum)
&& !tcx.has_global_allocator(cnum)
&& !tcx.has_panic_handler(cnum)
})
})
.cloned()
.collect();
// Collect all the extern crates (in a reliable order).
let mut crates_to_lint = vec![];
for id in tcx.hir().items() {
if matches!(tcx.def_kind(id.owner_id), DefKind::ExternCrate) {
let item = tcx.hir().item(id);
if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
crates_to_lint.push(ExternCrateToLint {
def_id: item.owner_id.to_def_id(),
span: item.span,
orig_name,
warn_if_unused: !item.ident.as_str().starts_with('_'),
});
}
}
}
let extern_prelude = &tcx.resolutions(()).extern_prelude;
for extern_crate in &crates_to_lint {
let def_id = extern_crate.def_id.expect_local();
let item = tcx.hir().expect_item(def_id);
// If the crate is fully unused, we suggest removing it altogether.
// We do this in any edition.
if extern_crate.warn_if_unused {
if let Some(&span) = unused_extern_crates.get(&def_id) {
// Removal suggestion span needs to include attributes (Issue #54400)
let id = tcx.hir().local_def_id_to_hir_id(def_id);
let span_with_attrs = tcx
.hir()
.attrs(id)
.iter()
.map(|attr| attr.span)
.fold(span, |acc, attr_span| acc.to(attr_span));
tcx.emit_spanned_lint(lint, id, span, UnusedExternCrate { span: span_with_attrs });
continue;
}
}
// If we are not in Rust 2018 edition, then we don't make any further
// suggestions.
if !tcx.sess.rust_2018() {
continue;
}
// If the extern crate isn't in the extern prelude,
// there is no way it can be written as a `use`.
let orig_name = extern_crate.orig_name.unwrap_or(item.ident.name);
if !extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) {
continue;
}
// If the extern crate is renamed, then we cannot suggest replacing it with a use as this
// would not insert the new name into the prelude, where other imports in the crate may be
// expecting it.
if extern_crate.orig_name.is_some() {
continue;
}
let id = tcx.hir().local_def_id_to_hir_id(def_id);
// If the extern crate has any attributes, they may have funky
// semantics we can't faithfully represent using `use` (most
// notably `#[macro_use]`). Ignore it.
if !tcx.hir().attrs(id).is_empty() {
continue;
}
let base_replacement = match extern_crate.orig_name {
Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name),
None => format!("use {};", item.ident.name),
};
let vis = tcx.sess.source_map().span_to_snippet(item.vis_span).unwrap_or_default();
let add_vis = |to| if vis.is_empty() { to } else { format!("{} {}", vis, to) };
tcx.emit_spanned_lint(
lint,
id,
extern_crate.span,
ExternCrateNotIdiomatic {
span: extern_crate.span,
msg_code: add_vis("use".to_string()),
suggestion_code: add_vis(base_replacement),
},
);
}
}
struct ExternCrateToLint {
/// `DefId` of the extern crate
def_id: DefId,
/// span from the item
span: Span,
/// if `Some`, then this is renamed (`extern crate orig_name as
/// crate_name`), and -- perhaps surprisingly -- this stores the
/// *original* name (`item.name` will contain the new name)
orig_name: Option<Symbol>,
/// if `false`, the original name started with `_`, so we shouldn't lint
/// about it going unused (but we should still emit idiom lints).
warn_if_unused: bool,
}

View file

@ -437,7 +437,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
}
// Here we are considering a case of converting
// `S<P0...Pn>` to S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
// `S<P0...Pn>` to `S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
// which acts like a pointer to `U`, but carries along some extra data of type `T`:
//
// struct Foo<T, U> {

View file

@ -3,7 +3,7 @@ use crate::astconv::AstConv;
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::Span;

View file

@ -17,13 +17,15 @@ use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeNa
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::*;
use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_session::lint;
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use std::fmt;
use crate::errors;
trait RegionExt {
fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
@ -161,6 +163,15 @@ enum Scope<'a> {
s: ScopeRef<'a>,
},
/// Disallows capturing non-lifetime binders from parent scopes.
///
/// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
/// since we don't do something more correct like replacing any captured
/// late-bound vars with early-bound params in the const's own generics.
AnonConstBoundary {
s: ScopeRef<'a>,
},
Root {
opt_parent_item: Option<LocalDefId>,
},
@ -211,6 +222,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
.field("s", &"..")
.finish(),
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
Scope::AnonConstBoundary { s: _ } => f.debug_struct("AnonConstBoundary").finish(),
Scope::Root { opt_parent_item } => {
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
}
@ -312,7 +324,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
break (vec![], BinderScopeType::Normal);
}
Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::AnonConstBoundary { s } => {
scope = s;
}
@ -1029,50 +1043,64 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow);
}
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
self.with(Scope::AnonConstBoundary { s: self.scope }, |this| {
intravisit::walk_anon_const(this, c);
});
}
}
fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault {
debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
let param_def_id = param_def_id.expect_local();
let parent_def_id = tcx.local_parent(param_def_id);
let generics = tcx.hir().get_generics(parent_def_id).unwrap();
let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(param_def_id) else {
bug!("expected GenericParam for object_lifetime_default");
};
match param.source {
hir::GenericParamSource::Generics => {
let parent_def_id = tcx.local_parent(param_def_id);
let generics = tcx.hir().get_generics(parent_def_id).unwrap();
let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
// Scan the bounds and where-clauses on parameters to extract bounds
// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
// for each type parameter.
match param.kind {
GenericParamKind::Type { .. } => {
let mut set = Set1::Empty;
// Scan the bounds and where-clauses on parameters to extract bounds
// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
// for each type parameter.
match param.kind {
GenericParamKind::Type { .. } => {
let mut set = Set1::Empty;
// Look for `type: ...` where clauses.
for bound in generics.bounds_for_param(param_def_id) {
// Ignore `for<'a> type: ...` as they can change what
// lifetimes mean (although we could "just" handle it).
if !bound.bound_generic_params.is_empty() {
continue;
}
// Look for `type: ...` where clauses.
for bound in generics.bounds_for_param(param_def_id) {
// Ignore `for<'a> type: ...` as they can change what
// lifetimes mean (although we could "just" handle it).
if !bound.bound_generic_params.is_empty() {
continue;
}
for bound in bound.bounds {
if let hir::GenericBound::Outlives(lifetime) = bound {
set.insert(lifetime.res);
for bound in bound.bounds {
if let hir::GenericBound::Outlives(lifetime) = bound {
set.insert(lifetime.res);
}
}
}
match set {
Set1::Empty => ObjectLifetimeDefault::Empty,
Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
Set1::One(hir::LifetimeName::Param(param_def_id)) => {
ObjectLifetimeDefault::Param(param_def_id.to_def_id())
}
_ => ObjectLifetimeDefault::Ambiguous,
}
}
}
match set {
Set1::Empty => ObjectLifetimeDefault::Empty,
Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
Set1::One(hir::LifetimeName::Param(param_def_id)) => {
ObjectLifetimeDefault::Param(param_def_id.to_def_id())
_ => {
bug!("object_lifetime_default_raw must only be called on a type parameter")
}
_ => ObjectLifetimeDefault::Ambiguous,
}
}
_ => {
bug!("object_lifetime_default_raw must only be called on a type parameter")
}
hir::GenericParamSource::Binder => ObjectLifetimeDefault::Empty,
}
}
@ -1267,7 +1295,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. } => {
| Scope::TraitRefBoundary { s, .. }
| Scope::AnonConstBoundary { s } => {
scope = s;
}
}
@ -1332,7 +1361,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
| Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. } => {
| Scope::TraitRefBoundary { s, .. }
| Scope::AnonConstBoundary { s } => {
scope = s;
}
}
@ -1351,6 +1381,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// search.
let mut late_depth = 0;
let mut scope = self.scope;
let mut crossed_anon_const = false;
let result = loop {
match *scope {
Scope::Body { s, .. } => {
@ -1384,17 +1415,44 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
| Scope::TraitRefBoundary { s, .. } => {
scope = s;
}
Scope::AnonConstBoundary { s } => {
crossed_anon_const = true;
scope = s;
}
}
};
if let Some(def) = result {
if let ResolvedArg::LateBound(..) = def && crossed_anon_const {
let use_span = self.tcx.hir().span(hir_id);
let def_span = self.tcx.def_span(param_def_id);
match self.tcx.def_kind(param_def_id) {
DefKind::ConstParam => {
self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const {
use_span,
def_span,
});
}
DefKind::TyParam => {
self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type {
use_span,
def_span,
});
}
_ => unreachable!(),
}
return;
}
self.map.defs.insert(hir_id, def);
return;
}
self.tcx
.sess
.delay_span_bug(self.tcx.hir().span(hir_id), "could not resolve {param_def_id:?}");
self.tcx.sess.delay_span_bug(
self.tcx.hir().span(hir_id),
format!("could not resolve {param_def_id:?}"),
);
}
#[instrument(level = "debug", skip(self))]
@ -1465,7 +1523,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
| Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. } => {
| Scope::TraitRefBoundary { s, .. }
| Scope::AnonConstBoundary { s } => {
scope = s;
}
}
@ -1701,7 +1760,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => {
Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. }
| Scope::AnonConstBoundary { s } => {
scope = s;
}
}

View file

@ -9,7 +9,7 @@ use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{
self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
self, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use rustc_span::symbol::Ident;
use rustc_span::{Span, DUMMY_SP};

View file

@ -5,7 +5,7 @@ use rustc_errors::{
error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
MultiSpan,
};
use rustc_macros::{Diagnostic, LintDiagnostic};
use rustc_macros::Diagnostic;
use rustc_middle::ty::Ty;
use rustc_span::{symbol::Ident, Span, Symbol};
@ -247,26 +247,6 @@ pub struct SubstsOnOverriddenImpl {
pub span: Span,
}
#[derive(LintDiagnostic)]
#[diag(hir_analysis_unused_extern_crate)]
pub struct UnusedExternCrate {
#[suggestion(applicability = "machine-applicable", code = "")]
pub span: Span,
}
#[derive(LintDiagnostic)]
#[diag(hir_analysis_extern_crate_not_idiomatic)]
pub struct ExternCrateNotIdiomatic {
#[suggestion(
style = "short",
applicability = "machine-applicable",
code = "{suggestion_code}"
)]
pub span: Span,
pub msg_code: String,
pub suggestion_code: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_const_impl_for_non_const_trait)]
pub struct ConstImplForNonConstTrait {
@ -401,3 +381,21 @@ pub(crate) struct VariadicFunctionCompatibleConvention<'a> {
pub span: Span,
pub conventions: &'a str,
}
#[derive(Diagnostic)]
pub(crate) enum CannotCaptureLateBoundInAnonConst {
#[diag(hir_analysis_cannot_capture_late_bound_ty_in_anon_const)]
Type {
#[primary_span]
use_span: Span,
#[label]
def_span: Span,
},
#[diag(hir_analysis_cannot_capture_late_bound_const_in_anon_const)]
Const {
#[primary_span]
use_span: Span,
#[label]
def_span: Span,
},
}

View file

@ -1,7 +1,7 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::Span;

View file

@ -8,7 +8,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
use rustc_middle::ty::{DefIdTree, TypeSuperVisitable, TypeVisitable};
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
use std::ops::ControlFlow;
/// Defines the `TermsContext` basically houses an arena where we can

View file

@ -315,7 +315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
probe::ProbeScope::TraitsInScope,
None,
) {
Ok(pick) => pick.self_ty,
Ok(pick) => eraser.fold_ty(pick.self_ty),
Err(_) => rcvr_ty,
};
// Remove one layer of references to account for `&mut self` and

View file

@ -25,7 +25,7 @@ use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{
self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, Ty, TyCtxt, UserType,
self, AdtKind, CanonicalUserType, GenericParamDefKind, Ty, TyCtxt, UserType,
};
use rustc_middle::ty::{GenericArgKind, SubstsRef, UserSelfTy, UserSubsts};
use rustc_session::lint;

View file

@ -3,9 +3,7 @@ use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def_id::DefId;
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::ty::{
self, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_span::{self, Span};
use rustc_trait_selection::traits;
@ -714,12 +712,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.parent(expr_ctor_def_id)
}
hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
// If this is a variant, its parent is the type definition.
if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
// For a typical enum like
// `enum Blah<T> { Variant(T) }`
// we get the following resolutions:
// - expr_ctor_def_id ::: DefId(0:29 ~ source_file[b442]::Blah::Variant::{constructor#0})
// - self.tcx.parent(expr_ctor_def_id) ::: DefId(0:28 ~ source_file[b442]::Blah::Variant)
// - self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) ::: DefId(0:26 ~ source_file[b442]::Blah)
// Therefore, we need to go up once to obtain the variant and up twice to obtain the type.
// Note that this pattern still holds even when we `use` a variant or `use` an enum type to rename it, or chain `use` expressions
// together; this resolution is handled automatically by `qpath_res`.
// FIXME: Deal with type aliases?
if in_ty_adt.did() == self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) {
// The constructor definition refers to the "constructor" of the variant:
// For example, `Some(5)` triggers this case.
self.tcx.parent(expr_ctor_def_id)
} else {
// FIXME: Deal with type aliases?
return Err(expr);
}
expr_ctor_def_id
}
_ => {
return Err(expr);

View file

@ -28,7 +28,7 @@ use rustc_infer::infer::InferOk;
use rustc_infer::infer::TypeTrace;
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty};
use rustc_middle::ty::{self, IsSuggestable, Ty};
use rustc_session::Session;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{self, sym, Span};
@ -36,7 +36,6 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}
use std::iter;
use std::mem;
use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn check_casts(&mut self) {
@ -1507,11 +1506,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let coerce = if blk.targeted_by_break {
CoerceMany::new(coerce_to_ty)
} else {
let tail_expr: &[&hir::Expr<'_>] = match tail_expr {
Some(e) => slice::from_ref(e),
None => &[],
};
CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice())
};
let prev_diverges = self.diverges.get();

View file

@ -16,7 +16,7 @@ use rustc_infer::traits::{self, StatementAsExpression};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
self, suggest_constraining_type_params, Binder, IsSuggestable, ToPredicate, Ty,
TypeVisitableExt,
};
use rustc_session::errors::ExprParenthesesNeeded;

View file

@ -5,6 +5,7 @@
#![feature(min_specialization)]
#![feature(control_flow_enum)]
#![feature(drain_filter)]
#![feature(option_as_slice)]
#![allow(rustc::potential_query_instability)]
#![recursion_limit = "256"]

View file

@ -636,7 +636,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
// `&&Some(x,)` `place_foo`
// `&Some(x,)` `deref { place_foo}`
// `Some(x,)` `deref { deref { place_foo }}`
// (x,)` `field0 { deref { deref { place_foo }}}` <- resulting place
// `(x,)` `field0 { deref { deref { place_foo }}}` <- resulting place
//
// The above example has no adjustments. If the code were instead the (after adjustments,
// equivalent) version

View file

@ -27,7 +27,7 @@ use rustc_middle::traits::util::supertraits;
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Symbol;
@ -333,6 +333,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
rcvr_ty.prefix_string(self.tcx),
ty_str_reported,
);
if tcx.sess.source_map().is_multiline(sugg_span) {
err.span_label(sugg_span.with_hi(span.lo()), "");
}
let ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
short_ty_str
} else {

View file

@ -13,7 +13,7 @@ use rustc_middle::ty::adjustment::{
};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
self, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
@ -749,14 +749,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let opname = Ident::with_dummy_span(opname);
let input_types =
opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default();
let (opt_rhs_expr, opt_rhs_ty) = opt_rhs.unzip();
let input_types = opt_rhs_ty.as_slice();
let cause = self.cause(
span,
traits::BinOp {
rhs_span: opt_rhs.map(|(expr, _)| expr.span),
is_lit: opt_rhs
.map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))),
rhs_span: opt_rhs_expr.map(|expr| expr.span),
is_lit: opt_rhs_expr
.map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
output_ty: expected.only_has_type(self),
},
);

View file

@ -11,7 +11,6 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already.
@ -393,11 +392,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(self.typeck_results.borrow().node_substs(expr.hir_id).type_at(1))
}
};
let arg_tys = match arg_ty {
None => &[],
Some(ref ty) => slice::from_ref(ty),
};
let arg_tys = arg_ty.as_slice();
let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op);
let method = match method {
Some(ok) => self.register_infer_ok_obligations(ok),

View file

@ -231,7 +231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We now fake capture information for all variables that are mentioned within the closure
// We do this after handling migrations so that min_captures computes before
if !enable_precise_capture(self.tcx, span) {
if !enable_precise_capture(span) {
let mut capture_information: InferredCaptureInformation<'tcx> = Default::default();
if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
@ -265,7 +265,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If we have an origin, store it.
if let Some(origin) = origin {
let origin = if enable_precise_capture(self.tcx, span) {
let origin = if enable_precise_capture(span) {
(origin.0, origin.1)
} else {
(origin.0, Place { projections: vec![], ..origin.1 })
@ -526,10 +526,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
base => bug!("Expected upvar, found={:?}", base),
};
let var_ident = self.tcx.hir().ident(var_hir_id);
let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else {
let mutability = self.determine_capture_mutability(&typeck_results, &place);
let min_cap_list = vec![ty::CapturedPlace {
var_ident,
place,
info: capture_info,
mutability,
@ -628,6 +630,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if !ancestor_found {
let mutability = self.determine_capture_mutability(&typeck_results, &place);
let captured_place = ty::CapturedPlace {
var_ident,
place,
info: updated_capture_info,
mutability,
@ -1240,8 +1243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
///
/// This will make more sense with an example:
///
/// ```rust
/// #![feature(capture_disjoint_fields)]
/// ```rust,edition2021
///
/// struct FancyInteger(i32); // This implements Drop
///
@ -2221,7 +2223,7 @@ fn determine_place_ancestry_relation<'tcx>(
/// || drop(&*m.a.field_of_a)
/// // Here we really do want to capture `*m.a` because that outlives `'static`
///
/// // If we capture `m`, then the closure no longer outlives `'static'
/// // If we capture `m`, then the closure no longer outlives `'static`
/// // it is constrained to `'a`
/// }
/// ```
@ -2247,12 +2249,10 @@ fn truncate_capture_for_optimization(
(place, curr_mode)
}
/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
/// user is using Rust Edition 2021 or higher.
///
/// Precise capture is enabled if user is using Rust Edition 2021 or higher.
/// `span` is the span of the closure.
fn enable_precise_capture(tcx: TyCtxt<'_>, span: Span) -> bool {
fn enable_precise_capture(span: Span) -> bool {
// We use span here to ensure that if the closure was generated by a macro with a different
// edition.
tcx.features().capture_disjoint_fields || span.rust_2021()
span.rust_2021()
}

View file

@ -18,7 +18,7 @@
//! the HIR doesn't change as a result of the annotations, which might
//! perturb the reuse results.
//!
//! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
//! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]`
//! allows for doing a more fine-grained check to see if pre- or post-lto data
//! was re-used.

View file

@ -1870,7 +1870,7 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
}
}
/// Subtracts `set from `row`. `set` can be either `BitSet` or
/// Subtracts `set` from `row`. `set` can be either `BitSet` or
/// `HybridBitSet`. Has no effect if `row` does not exist.
///
/// Returns true if the row was changed.

View file

@ -79,7 +79,7 @@ infer_subtype = ...so that the {$requirement ->
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] #[start]` function has the correct type
[fn_start_correct_type] `#[start]` function has the correct type
[intristic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
@ -92,7 +92,7 @@ infer_subtype_2 = ...so that {$requirement ->
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] #[start]` function has the correct type
[fn_start_correct_type] `#[start]` function has the correct type
[intristic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
@ -277,7 +277,7 @@ infer_tid_consider_borrowing = consider borrowing this type parameter in the tra
infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s 'static` requirement
infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
@ -313,7 +313,7 @@ infer_but_needs_to_satisfy = {$has_param_name ->
[false] ...and is required to live as long as `'static` here
}
.used_here = ...is used here...
.introduced_by_bound = 'static` lifetime requirement introduced by this bound
.introduced_by_bound = `'static` lifetime requirement introduced by this bound
infer_more_targeted = {$has_param_name ->
[true] `{$param_name}`
@ -345,3 +345,6 @@ infer_prlf_defined_without_sub = the lifetime defined here...
infer_prlf_must_oultive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
infer_prlf_must_oultive_without_sup = ...must outlive the lifetime defined here
infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
.label = opaque type defined here

View file

@ -1147,3 +1147,13 @@ pub enum PlaceholderRelationLfNotSatisfied {
note: (),
},
}
#[derive(Diagnostic)]
#[diag(infer_opaque_captures_lifetime, code = "E0700")]
pub struct OpaqueCapturesLifetime<'tcx> {
#[primary_span]
pub span: Span,
#[label]
pub opaque_ty_span: Span,
pub opaque_ty: Ty<'tcx>,
}

View file

@ -369,6 +369,34 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
}
}
impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
fn to_trace(
_: TyCtxt<'tcx>,
cause: &ObligationCause<'tcx>,
a_is_expected: bool,
a: Self,
b: Self,
) -> TypeTrace<'tcx> {
use GenericArgKind::*;
TypeTrace {
cause: cause.clone(),
values: match (a.unpack(), b.unpack()) {
(Lifetime(a), Lifetime(b)) => Regions(ExpectedFound::new(a_is_expected, a, b)),
(Type(a), Type(b)) => Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
(Const(a), Const(b)) => {
Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
}
(Lifetime(_), Type(_) | Const(_))
| (Type(_), Lifetime(_) | Const(_))
| (Const(_), Lifetime(_) | Type(_)) => {
bug!("relating different kinds: {a:?} {b:?}")
}
},
}
}
}
impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
fn to_trace(
_: TyCtxt<'tcx>,

View file

@ -50,7 +50,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// Like [Self::canonicalize_query], but preserves distinct universes. For
/// example, canonicalizing `&'?0: Trait<'?1>`, where `'?0` is in `U1` and
/// `'?1` is in `U3` would be canonicalized to have ?0` in `U1` and `'?1`
/// `'?1` is in `U3` would be canonicalized to have `?0` in `U1` and `'?1`
/// in `U2`.
///
/// This is used for Chalk integration.

View file

@ -30,7 +30,7 @@ use rustc_middle::ty::{self, List, TyCtxt};
use rustc_span::source_map::Span;
pub use rustc_middle::infer::canonical::*;
use substitute::CanonicalExt;
pub use substitute::CanonicalExt;
mod canonicalizer;
pub mod query_response;
@ -100,7 +100,11 @@ impl<'tcx> InferCtxt<'tcx> {
/// variable for it. If this is an existentially quantified
/// variable, then you'll get a new inference variable; if it is a
/// universally quantified variable, you get a placeholder.
fn instantiate_canonical_var(
///
/// FIXME(-Ztrait-solver=next): This is public because it's used by the
/// new trait solver which has a different canonicalization routine.
/// We should somehow deduplicate all of this.
pub fn instantiate_canonical_var(
&self,
span: Span,
cv_info: CanonicalVarInfo<'tcx>,

View file

@ -151,11 +151,21 @@ impl<'tcx> InferCtxt<'tcx> {
})
}
/// FIXME: This method should only be used for canonical queries and therefore be private.
///
/// As the new solver does canonicalization slightly differently, this is also used there
/// for now. This should hopefully change fairly soon.
pub fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
/// Used by the new solver as that one takes the opaque types at the end of a probe
/// to deal with multiple candidates without having to recompute them.
pub fn clone_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
self.inner
.borrow()
.opaque_type_storage
.opaque_types
.iter()
.map(|&(k, ref v)| {
(self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty)
})
.collect()
}
fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
.into_iter()
.map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))

View file

@ -11,7 +11,9 @@ use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, TyCtxt};
pub(super) trait CanonicalExt<'tcx, V> {
/// FIXME(-Ztrait-solver=next): This or public because it is shared with the
/// new trait solver implementation. We should deduplicate canonicalization.
pub trait CanonicalExt<'tcx, V> {
/// Instantiate the wrapped value, replacing each canonical value
/// with the value given in `var_values`.
fn substitute(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V

View file

@ -49,6 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError;
use super::region_constraints::GenericKind;
use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
use crate::errors;
use crate::infer;
use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
use crate::infer::ExpectedFound;
@ -281,15 +282,13 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
span: Span,
hidden_ty: Ty<'tcx>,
hidden_region: ty::Region<'tcx>,
opaque_ty: ty::OpaqueTypeKey<'tcx>,
opaque_ty_key: ty::OpaqueTypeKey<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let opaque_ty = tcx.mk_opaque(opaque_ty.def_id.to_def_id(), opaque_ty.substs);
let mut err = struct_span_err!(
tcx.sess,
let mut err = tcx.sess.create_err(errors::OpaqueCapturesLifetime {
span,
E0700,
"hidden type for `{opaque_ty}` captures lifetime that does not appear in bounds",
);
opaque_ty: tcx.mk_opaque(opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs),
opaque_ty_span: tcx.def_span(opaque_ty_key.def_id),
});
// Explain the region we are capturing.
match *hidden_region {
@ -1690,7 +1689,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
format!("{name} is defined in the current crate")
} else {
let crate_name = self.tcx.crate_name(defid.krate);
format!("{name} is defined in crate `{crate_name}")
format!("{name} is defined in crate `{crate_name}`")
};
diagnostic.span_note(def_span, msg);
};

View file

@ -17,7 +17,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
use rustc_middle::ty::{self, DefIdTree, InferConst};
use rustc_middle::ty::{self, InferConst};
use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
use rustc_span::symbol::{kw, sym, Ident};

Some files were not shown because too many files have changed in this diff Show more