Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #104599

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
9f0a862
Improve generating Custom entry function
Ayush1325 Nov 5, 2022
1c56a53
constify remaining layout methods
CraftSpider Sep 23, 2022
c207dc9
Add stability for alignment
CraftSpider Oct 17, 2022
3860cb1
Update with derive_const
CraftSpider Nov 12, 2022
21c61e1
Add derive_const feature
CraftSpider Nov 13, 2022
c8e5ac4
Fix issue number
CraftSpider Nov 13, 2022
bbcdebd
Use ? instead of match
CraftSpider Nov 13, 2022
45f441a
nll: correctly deal with bivariance
lcnr Nov 14, 2022
6aa611a
mv utility methods into separate module
lcnr Nov 15, 2022
f5f6761
add comment about opaque types
lcnr Nov 15, 2022
b2e6d08
use `ocx` type relation routines
lcnr Nov 15, 2022
6dfe239
Use custom entry name in gcc
Ayush1325 Nov 15, 2022
2436dff
Use custom entry name in cranelift
Ayush1325 Nov 17, 2022
57e7261
Properly link `{Once,Lazy}{Cell,Lock}` in docs
WaffleLapkin Nov 17, 2022
e3036df
couple of clippy::perf fixes
matthiaskrgr Nov 18, 2022
c1ec8ff
dont unchecked create `ErrorGuaranteed` in `BorrowckErrors`
BoxyUwU Nov 17, 2022
9c51004
`InferCtxt::is_tainted_by_errors` returns `ErrorGuaranteed`
BoxyUwU Nov 17, 2022
95a267b
make `replaced_with_error` store `ErrorGuaranteed`
BoxyUwU Nov 17, 2022
3fca95a
`track_errors` use a delay_span_bug
BoxyUwU Nov 17, 2022
1c48039
rename `is_tainted_by_errors`
BoxyUwU Nov 18, 2022
9ed3483
require an `ErrorGuaranteed` to taint infcx with errors
BoxyUwU Nov 18, 2022
45a09a4
review comments 2 electric boogalo
BoxyUwU Nov 18, 2022
4e504c7
deduplicate tests
lcnr Nov 18, 2022
df7ecbc
diagnostics: only show one suggestion for method -> assoc fn
notriddle Nov 18, 2022
4ca5ece
Rollup merge of #102207 - CraftSpider:const-layout, r=scottmcm
Dylan-DPC Nov 19, 2022
3bd8ac8
Rollup merge of #104001 - Ayush1325:custom-entry, r=bjorn3
Dylan-DPC Nov 19, 2022
de29cb1
Rollup merge of #104411 - lcnr:bivariance-nll, r=compiler-errors
Dylan-DPC Nov 19, 2022
266e957
Rollup merge of #104528 - WaffleLapkin:lazy_lock_docfix, r=matklad
Dylan-DPC Nov 19, 2022
e1bb455
Rollup merge of #104554 - BoxyUwU:less_unchecked_pls, r=lcnr
Dylan-DPC Nov 19, 2022
48c3859
Rollup merge of #104566 - matthiaskrgr:clippy_perf_nov18, r=oli-obk
Dylan-DPC Nov 19, 2022
a0da5e9
Rollup merge of #104575 - lcnr:dedup-tests, r=jackh726
Dylan-DPC Nov 19, 2022
bbad798
Rollup merge of #104580 - notriddle:notriddle/issue-102354-hide-sugg,…
Dylan-DPC Nov 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ extern crate tracing;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_data_structures::vec_map::VecMap;
use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_errors::{Diagnostic, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::ChunkedBitSet;
Expand Down Expand Up @@ -192,13 +192,13 @@ fn do_mir_borrowck<'tcx>(
}
}

let mut errors = error::BorrowckErrors::new();
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(ErrorGuaranteed { .. }) = tables.tainted_by_errors {
infcx.set_tainted_by_errors();
errors.set_tainted_by_errors();
if let Some(e) = tables.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)
Expand Down Expand Up @@ -2260,6 +2260,7 @@ mod error {
use super::*;

pub struct BorrowckErrors<'tcx> {
tcx: TyCtxt<'tcx>,
/// This field keeps track of move errors that are to be reported for given move indices.
///
/// There are situations where many errors can be reported for a single move out (see #53807)
Expand All @@ -2282,28 +2283,33 @@ mod error {
tainted_by_errors: Option<ErrorGuaranteed>,
}

impl BorrowckErrors<'_> {
pub fn new() -> Self {
impl<'tcx> BorrowckErrors<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
BorrowckErrors {
tcx,
buffered_move_errors: BTreeMap::new(),
buffered: Default::default(),
tainted_by_errors: None,
}
}

// FIXME(eddyb) this is a suboptimal API because `tainted_by_errors` is
// set before any emission actually happens (weakening the guarantee).
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
if let None = self.tainted_by_errors {
self.tainted_by_errors = Some(
self.tcx
.sess
.delay_span_bug(t.span.clone(), "diagnostic buffered but not emitted"),
)
}
t.buffer(&mut self.buffered);
}

pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) {
t.buffer(&mut self.buffered);
}

pub fn set_tainted_by_errors(&mut self) {
self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
pub fn set_tainted_by_errors(&mut self, e: ErrorGuaranteed) {
self.tainted_by_errors = Some(e);
}
}

Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_borrowck/src/nll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,10 @@ pub(crate) fn compute_regions<'cx, 'tcx>(

if !nll_errors.is_empty() {
// Suppress unhelpful extra errors in `infer_opaque_types`.
infcx.set_tainted_by_errors();
infcx.set_tainted_by_errors(infcx.tcx.sess.delay_span_bug(
body.span,
"`compute_regions` tainted `infcx` with errors but did not emit any errors",
));
}

let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
instantiated_ty: OpaqueHiddenType<'tcx>,
origin: OpaqueTyOrigin,
) -> Ty<'tcx> {
if self.is_tainted_by_errors() {
return self.tcx.ty_error();
if let Some(e) = self.tainted_by_errors() {
return self.tcx.ty_error_with_guaranteed(e);
}

let definition_ty = instantiated_ty
Expand Down
25 changes: 15 additions & 10 deletions compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,19 @@ fn clif_sig_from_fn_abi<'tcx>(
default_call_conv: CallConv,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) -> Signature {
let call_conv = match fn_abi.conv {
let call_conv = conv_to_call_conv(fn_abi.conv, default_call_conv);

let inputs = fn_abi.args.iter().map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()).flatten();

let (return_ptr, returns) = fn_abi.ret.get_abi_return(tcx);
// Sometimes the first param is an pointer to the place where the return value needs to be stored.
let params: Vec<_> = return_ptr.into_iter().chain(inputs).collect();

Signature { params, returns, call_conv }
}

pub(crate) fn conv_to_call_conv(c: Conv, default_call_conv: CallConv) -> CallConv {
match c {
Conv::Rust | Conv::C => default_call_conv,
Conv::RustCold => CallConv::Cold,
Conv::X86_64SysV => CallConv::SystemV,
Expand All @@ -38,15 +50,8 @@ fn clif_sig_from_fn_abi<'tcx>(
| Conv::X86VectorCall
| Conv::AmdGpuKernel
| Conv::AvrInterrupt
| Conv::AvrNonBlockingInterrupt => todo!("{:?}", fn_abi.conv),
};
let inputs = fn_abi.args.iter().map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()).flatten();

let (return_ptr, returns) = fn_abi.ret.get_abi_return(tcx);
// Sometimes the first param is an pointer to the place where the return value needs to be stored.
let params: Vec<_> = return_ptr.into_iter().chain(inputs).collect();

Signature { params, returns, call_conv }
| Conv::AvrNonBlockingInterrupt => todo!("{:?}", c),
}
}

pub(crate) fn get_function_sig<'tcx>(
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_codegen_cranelift/src/main_shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,14 @@ pub(crate) fn maybe_create_entry_wrapper(
AbiParam::new(m.target_config().pointer_type()),
],
returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)],
call_conv: CallConv::triple_default(m.isa().triple()),
call_conv: crate::conv_to_call_conv(
tcx.sess.target.options.entry_abi,
CallConv::triple_default(m.isa().triple()),
),
};

let cmain_func_id = m.declare_function("main", Linkage::Export, &cmain_sig).unwrap();
let entry_name = tcx.sess.target.options.entry_name.as_ref();
let cmain_func_id = m.declare_function(entry_name, Linkage::Export, &cmain_sig).unwrap();

let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);

Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_codegen_gcc/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,9 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}

fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
if self.get_declared_value("main").is_none() {
Some(self.declare_cfn("main", fn_type))
let entry_name = self.sess().target.entry_name.as_ref();
if self.get_declared_value(entry_name).is_none() {
Some(self.declare_entry_fn(entry_name, fn_type, ()))
}
else {
// If the symbol already exists, it is an error: for example, the user wrote
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_gcc/src/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
global
}

pub fn declare_cfn(&self, name: &str, _fn_type: Type<'gcc>) -> RValue<'gcc> {
pub fn declare_entry_fn(&self, name: &str, _fn_type: Type<'gcc>, callconv: () /*llvm::CCallConv*/) -> RValue<'gcc> {
// TODO(antoyo): use the fn_type parameter.
let const_string = self.context.new_type::<u8>().make_pointer().make_pointer();
let return_type = self.type_i32();
let variadic = false;
self.linkage.set(FunctionType::Exported);
let func = declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, &[self.type_i32(), const_string], variadic);
let func = declare_raw_fn(self, name, callconv, return_type, &[self.type_i32(), const_string], variadic);
// NOTE: it is needed to set the current_func here as well, because get_fn() is not called
// for the main function.
*self.current_func.borrow_mut() = Some(func);
Expand Down
40 changes: 23 additions & 17 deletions compiler/rustc_codegen_llvm/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,23 +398,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
}

fn llvm_cconv(&self) -> llvm::CallConv {
match self.conv {
Conv::C | Conv::Rust | Conv::CCmseNonSecureCall => llvm::CCallConv,
Conv::RustCold => llvm::ColdCallConv,
Conv::AmdGpuKernel => llvm::AmdGpuKernel,
Conv::AvrInterrupt => llvm::AvrInterrupt,
Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt,
Conv::ArmAapcs => llvm::ArmAapcsCallConv,
Conv::Msp430Intr => llvm::Msp430Intr,
Conv::PtxKernel => llvm::PtxKernel,
Conv::X86Fastcall => llvm::X86FastcallCallConv,
Conv::X86Intr => llvm::X86_Intr,
Conv::X86Stdcall => llvm::X86StdcallCallConv,
Conv::X86ThisCall => llvm::X86_ThisCall,
Conv::X86VectorCall => llvm::X86_VectorCall,
Conv::X86_64SysV => llvm::X86_64_SysV,
Conv::X86_64Win64 => llvm::X86_64_Win64,
}
self.conv.into()
}

fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
Expand Down Expand Up @@ -596,3 +580,25 @@ impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
llvm::get_param(self.llfn(), index as c_uint)
}
}

impl From<Conv> for llvm::CallConv {
fn from(conv: Conv) -> Self {
match conv {
Conv::C | Conv::Rust | Conv::CCmseNonSecureCall => llvm::CCallConv,
Conv::RustCold => llvm::ColdCallConv,
Conv::AmdGpuKernel => llvm::AmdGpuKernel,
Conv::AvrInterrupt => llvm::AvrInterrupt,
Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt,
Conv::ArmAapcs => llvm::ArmAapcsCallConv,
Conv::Msp430Intr => llvm::Msp430Intr,
Conv::PtxKernel => llvm::PtxKernel,
Conv::X86Fastcall => llvm::X86FastcallCallConv,
Conv::X86Intr => llvm::X86_Intr,
Conv::X86Stdcall => llvm::X86StdcallCallConv,
Conv::X86ThisCall => llvm::X86_ThisCall,
Conv::X86VectorCall => llvm::X86_VectorCall,
Conv::X86_64SysV => llvm::X86_64_SysV,
Conv::X86_64Win64 => llvm::X86_64_Win64,
}
}
}
10 changes: 8 additions & 2 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,14 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}

fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
if self.get_declared_value("main").is_none() {
Some(self.declare_cfn("main", llvm::UnnamedAddr::Global, fn_type))
let entry_name = self.sess().target.entry_name.as_ref();
if self.get_declared_value(entry_name).is_none() {
Some(self.declare_entry_fn(
entry_name,
self.sess().target.entry_abi.into(),
llvm::UnnamedAddr::Global,
fn_type,
))
} else {
// If the symbol already exists, it is an error: for example, the user wrote
// #[no_mangle] extern "C" fn main(..) {..}
Expand Down
22 changes: 22 additions & 0 deletions compiler/rustc_codegen_llvm/src/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,28 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type)
}

/// Declare an entry Function
///
/// The ABI of this function can change depending on the target (although for now the same as
/// `declare_cfn`)
///
/// If there’s a value with the same name already declared, the function will
/// update the declaration and return existing Value instead.
pub fn declare_entry_fn(
&self,
name: &str,
callconv: llvm::CallConv,
unnamed: llvm::UnnamedAddr,
fn_type: &'ll Type,
) -> &'ll Value {
let visibility = if self.tcx.sess.target.default_hidden_visibility {
llvm::Visibility::Hidden
} else {
llvm::Visibility::Default
};
declare_raw_fn(self, name, callconv, unnamed, visibility, fn_type)
}

/// Declare a Rust function.
///
/// If there’s a value with the same name already declared, the function will
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ fn exported_symbols_provider_local<'tcx>(
.collect();

if tcx.entry_fn(()).is_some() {
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, "main"));
let exported_symbol =
ExportedSymbol::NoDefId(SymbolName::new(tcx, tcx.sess.target.entry_name.as_ref()));

symbols.push((
exported_symbol,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use super::{
MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, PointerArithmetic, Provenance,
Scalar, StackPopJump,
};
use crate::transform::validate::equal_up_to_regions;
use crate::util;

pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
/// Stores the `Machine` instance.
Expand Down Expand Up @@ -354,8 +354,8 @@ pub(super) fn mir_assign_valid_types<'tcx>(
// Type-changing assignments can happen when subtyping is used. While
// all normal lifetimes are erased, higher-ranked types with their
// late-bound lifetimes are still around and can lead to type
// differences. So we compare ignoring lifetimes.
if equal_up_to_regions(tcx, param_env, src.ty, dest.ty) {
// differences.
if util::is_subtype(tcx, param_env, src.ty, dest.ty) {
// Make sure the layout is equal, too -- just to be safe. Miri really
// needs layout equality. For performance reason we skip this check when
// the types are equal. Equal types *can* have different layouts when
Expand Down
59 changes: 2 additions & 57 deletions compiler/rustc_const_eval/src/transform/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use rustc_data_structures::fx::FxHashSet;
use rustc_index::bit_set::BitSet;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
Expand All @@ -12,8 +11,7 @@ use rustc_middle::mir::{
ProjectionElem, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator,
TerminatorKind, UnOp, START_BLOCK,
};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypeVisitable};
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitable};
use rustc_mir_dataflow::impls::MaybeStorageLive;
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_mir_dataflow::{Analysis, ResultsCursor};
Expand Down Expand Up @@ -70,44 +68,6 @@ impl<'tcx> MirPass<'tcx> for Validator {
}
}

/// Returns whether the two types are equal up to lifetimes.
/// All lifetimes, including higher-ranked ones, get ignored for this comparison.
/// (This is unlike the `erasing_regions` methods, which keep higher-ranked lifetimes for soundness reasons.)
///
/// The point of this function is to approximate "equal up to subtyping". However,
/// the approximation is incorrect as variance is ignored.
pub fn equal_up_to_regions<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
src: Ty<'tcx>,
dest: Ty<'tcx>,
) -> bool {
// Fast path.
if src == dest {
return true;
}

// Normalize lifetimes away on both sides, then compare.
let normalize = |ty: Ty<'tcx>| {
tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty).fold_with(
&mut BottomUpFolder {
tcx,
// FIXME: We erase all late-bound lifetimes, but this is not fully correct.
// If you have a type like `<for<'a> fn(&'a u32) as SomeTrait>::Assoc`,
// this is not necessarily equivalent to `<fn(&'static u32) as SomeTrait>::Assoc`,
// since one may have an `impl SomeTrait for fn(&32)` and
// `impl SomeTrait for fn(&'static u32)` at the same time which
// specify distinct values for Assoc. (See also #56105)
lt_op: |_| tcx.lifetimes.re_erased,
// Leave consts and types unchanged.
ct_op: |ct| ct,
ty_op: |ty| ty,
},
)
};
tcx.infer_ctxt().build().can_eq(param_env, normalize(src), normalize(dest)).is_ok()
}

struct TypeChecker<'a, 'tcx> {
when: &'a str,
body: &'a Body<'tcx>,
Expand Down Expand Up @@ -183,22 +143,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
return true;
}

// Normalize projections and things like that.
// Type-changing assignments can happen when subtyping is used. While
// all normal lifetimes are erased, higher-ranked types with their
// late-bound lifetimes are still around and can lead to type
// differences. So we compare ignoring lifetimes.

// First, try with reveal_all. This might not work in some cases, as the predicates
// can be cleared in reveal_all mode. We try the reveal first anyways as it is used
// by some other passes like inlining as well.
let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
if equal_up_to_regions(self.tcx, param_env, src, dest) {
return true;
}

// If this fails, we can try it without the reveal.
equal_up_to_regions(self.tcx, self.param_env, src, dest)
crate::util::is_subtype(self.tcx, self.param_env, src, dest)
}
}

Expand Down
Loading