Auto merge of #113370 - compiler-errors:rollup-8gvyy8e, r=compiler-errors
Rollup of 8 pull requests Successful merges: - #113010 (rust-installer & rls: remove exclusion from rustfmt & tidy ) - #113317 ( -Ztrait-solver=next: stop depending on old solver) - #113319 (`TypeParameterDefinition` always require a `DefId`) - #113320 (Add some extra information to opaque type cycle errors) - #113321 (Move `ty::ConstKind` to `rustc_type_ir`) - #113337 (Winnow specialized impls during selection in new solver) - #113355 (Move most coverage code out of `rustc_codegen_ssa`) - #113356 (Add support for NetBSD/riscv64 aka. riscv64gc-unknown-netbsd.) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5dac6b320b
84 changed files with 1988 additions and 1412 deletions
|
@ -706,7 +706,6 @@ fn codegen_stmt<'tcx>(
|
||||||
let times = fx
|
let times = fx
|
||||||
.monomorphize(times)
|
.monomorphize(times)
|
||||||
.eval(fx.tcx, ParamEnv::reveal_all())
|
.eval(fx.tcx, ParamEnv::reveal_all())
|
||||||
.kind()
|
|
||||||
.try_to_bits(fx.tcx.data_layout.pointer_size)
|
.try_to_bits(fx.tcx.data_layout.pointer_size)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if operand.layout().size.bytes() == 0 {
|
if operand.layout().size.bytes() == 0 {
|
||||||
|
|
|
@ -1,69 +1,11 @@
|
||||||
use gccjit::RValue;
|
use rustc_codegen_ssa::traits::CoverageInfoBuilderMethods;
|
||||||
use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods};
|
use rustc_middle::mir::Coverage;
|
||||||
use rustc_hir::def_id::DefId;
|
|
||||||
use rustc_middle::mir::coverage::{
|
|
||||||
CodeRegion,
|
|
||||||
CounterValueReference,
|
|
||||||
ExpressionOperandId,
|
|
||||||
InjectedExpressionId,
|
|
||||||
Op,
|
|
||||||
};
|
|
||||||
use rustc_middle::ty::Instance;
|
use rustc_middle::ty::Instance;
|
||||||
|
|
||||||
use crate::builder::Builder;
|
use crate::builder::Builder;
|
||||||
use crate::context::CodegenCx;
|
|
||||||
|
|
||||||
impl<'a, 'gcc, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
impl<'a, 'gcc, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||||
fn set_function_source_hash(
|
fn add_coverage(&mut self, _instance: Instance<'tcx>, _coverage: &Coverage) {
|
||||||
&mut self,
|
|
||||||
_instance: Instance<'tcx>,
|
|
||||||
_function_source_hash: u64,
|
|
||||||
) -> bool {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_coverage_counter(&mut self, _instance: Instance<'tcx>, _id: CounterValueReference, _region: CodeRegion) -> bool {
|
|
||||||
// TODO(antoyo)
|
// TODO(antoyo)
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_coverage_counter_expression(&mut self, _instance: Instance<'tcx>, _id: InjectedExpressionId, _lhs: ExpressionOperandId, _op: Op, _rhs: ExpressionOperandId, _region: Option<CodeRegion>) -> bool {
|
|
||||||
// TODO(antoyo)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_coverage_unreachable(&mut self, _instance: Instance<'tcx>, _region: CodeRegion) -> bool {
|
|
||||||
// TODO(antoyo)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'gcc, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|
||||||
fn coverageinfo_finalize(&self) {
|
|
||||||
// TODO(antoyo)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_pgo_func_name_var(&self, _instance: Instance<'tcx>) -> RValue<'gcc> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Functions with MIR-based coverage are normally codegenned _only_ if
|
|
||||||
/// called. LLVM coverage tools typically expect every function to be
|
|
||||||
/// defined (even if unused), with at least one call to LLVM intrinsic
|
|
||||||
/// `instrprof.increment`.
|
|
||||||
///
|
|
||||||
/// Codegen a small function that will never be called, with one counter
|
|
||||||
/// that will never be incremented.
|
|
||||||
///
|
|
||||||
/// For used/called functions, the coverageinfo was already added to the
|
|
||||||
/// `function_coverage_map` (keyed by function `Instance`) during codegen.
|
|
||||||
/// But in this case, since the unused function was _not_ previously
|
|
||||||
/// codegenned, collect the coverage `CodeRegion`s from the MIR and add
|
|
||||||
/// them. The first `CodeRegion` is used to add a single counter, with the
|
|
||||||
/// same counter ID used in the injected `instrprof.increment` intrinsic
|
|
||||||
/// call. Since the function is never called, all other `CodeRegion`s can be
|
|
||||||
/// added as `unreachable_region`s.
|
|
||||||
fn define_unused_fn(&self, _def_id: DefId) {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
pub use super::ffi::*;
|
pub use super::ffi::*;
|
||||||
|
|
||||||
use rustc_index::{IndexSlice, IndexVec};
|
use rustc_index::{IndexSlice, IndexVec};
|
||||||
|
use rustc_middle::bug;
|
||||||
use rustc_middle::mir::coverage::{
|
use rustc_middle::mir::coverage::{
|
||||||
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId,
|
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId,
|
||||||
InjectedExpressionIndex, MappedExpressionIndex, Op,
|
InjectedExpressionIndex, MappedExpressionIndex, Op,
|
|
@ -1,10 +1,10 @@
|
||||||
use crate::common::CodegenCx;
|
use crate::common::CodegenCx;
|
||||||
use crate::coverageinfo;
|
use crate::coverageinfo;
|
||||||
|
use crate::coverageinfo::map_data::{Counter, CounterExpression};
|
||||||
use crate::llvm;
|
use crate::llvm;
|
||||||
|
|
||||||
use llvm::coverageinfo::CounterMappingRegion;
|
use llvm::coverageinfo::CounterMappingRegion;
|
||||||
use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression};
|
use rustc_codegen_ssa::traits::ConstMethods;
|
||||||
use rustc_codegen_ssa::traits::{ConstMethods, CoverageInfoMethods};
|
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
|
|
@ -3,13 +3,13 @@ use crate::llvm;
|
||||||
use crate::abi::Abi;
|
use crate::abi::Abi;
|
||||||
use crate::builder::Builder;
|
use crate::builder::Builder;
|
||||||
use crate::common::CodegenCx;
|
use crate::common::CodegenCx;
|
||||||
|
use crate::coverageinfo::map_data::{CounterExpression, FunctionCoverage};
|
||||||
|
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use llvm::coverageinfo::CounterMappingRegion;
|
use llvm::coverageinfo::CounterMappingRegion;
|
||||||
use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, FunctionCoverage};
|
|
||||||
use rustc_codegen_ssa::traits::{
|
use rustc_codegen_ssa::traits::{
|
||||||
BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, CoverageInfoMethods,
|
BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, MiscMethods,
|
||||||
MiscMethods, StaticMethods,
|
StaticMethods,
|
||||||
};
|
};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -17,16 +17,19 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_llvm::RustString;
|
use rustc_llvm::RustString;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::mir::coverage::{
|
use rustc_middle::mir::coverage::{
|
||||||
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op,
|
CodeRegion, CounterValueReference, CoverageKind, ExpressionOperandId, InjectedExpressionId, Op,
|
||||||
};
|
};
|
||||||
|
use rustc_middle::mir::Coverage;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::layout::FnAbiOf;
|
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||||
use rustc_middle::ty::subst::InternalSubsts;
|
use rustc_middle::ty::subst::InternalSubsts;
|
||||||
use rustc_middle::ty::Instance;
|
use rustc_middle::ty::Instance;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
|
||||||
|
mod ffi;
|
||||||
|
pub(crate) mod map_data;
|
||||||
pub mod mapgen;
|
pub mod mapgen;
|
||||||
|
|
||||||
const UNUSED_FUNCTION_COUNTER_ID: CounterValueReference = CounterValueReference::START;
|
const UNUSED_FUNCTION_COUNTER_ID: CounterValueReference = CounterValueReference::START;
|
||||||
|
@ -53,11 +56,17 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
// These methods used to be part of trait `CoverageInfoMethods`, which no longer
|
||||||
fn coverageinfo_finalize(&self) {
|
// exists after most coverage code was moved out of SSA.
|
||||||
|
impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||||
|
pub(crate) fn coverageinfo_finalize(&self) {
|
||||||
mapgen::finalize(self)
|
mapgen::finalize(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For LLVM codegen, returns a function-specific `Value` for a global
|
||||||
|
/// string, to hold the function name passed to LLVM intrinsic
|
||||||
|
/// `instrprof.increment()`. The `Value` is only created once per instance.
|
||||||
|
/// Multiple invocations with the same instance return the same `Value`.
|
||||||
fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value {
|
fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value {
|
||||||
if let Some(coverage_context) = self.coverage_context() {
|
if let Some(coverage_context) = self.coverage_context() {
|
||||||
debug!("getting pgo_func_name_var for instance={:?}", instance);
|
debug!("getting pgo_func_name_var for instance={:?}", instance);
|
||||||
|
@ -94,6 +103,54 @@ impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
||||||
|
fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage) {
|
||||||
|
let bx = self;
|
||||||
|
|
||||||
|
let Coverage { kind, code_region } = coverage.clone();
|
||||||
|
match kind {
|
||||||
|
CoverageKind::Counter { function_source_hash, id } => {
|
||||||
|
if bx.set_function_source_hash(instance, function_source_hash) {
|
||||||
|
// If `set_function_source_hash()` returned true, the coverage map is enabled,
|
||||||
|
// so continue adding the counter.
|
||||||
|
if let Some(code_region) = code_region {
|
||||||
|
// Note: Some counters do not have code regions, but may still be referenced
|
||||||
|
// from expressions. In that case, don't add the counter to the coverage map,
|
||||||
|
// but do inject the counter intrinsic.
|
||||||
|
bx.add_coverage_counter(instance, id, code_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
let coverageinfo = bx.tcx().coverageinfo(instance.def);
|
||||||
|
|
||||||
|
let fn_name = bx.get_pgo_func_name_var(instance);
|
||||||
|
let hash = bx.const_u64(function_source_hash);
|
||||||
|
let num_counters = bx.const_u32(coverageinfo.num_counters);
|
||||||
|
let index = bx.const_u32(id.zero_based_index());
|
||||||
|
debug!(
|
||||||
|
"codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
|
||||||
|
fn_name, hash, num_counters, index,
|
||||||
|
);
|
||||||
|
bx.instrprof_increment(fn_name, hash, num_counters, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CoverageKind::Expression { id, lhs, op, rhs } => {
|
||||||
|
bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region);
|
||||||
|
}
|
||||||
|
CoverageKind::Unreachable => {
|
||||||
|
bx.add_coverage_unreachable(
|
||||||
|
instance,
|
||||||
|
code_region.expect("unreachable regions always have code regions"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These methods used to be part of trait `CoverageInfoBuilderMethods`, but
|
||||||
|
// after moving most coverage code out of SSA they are now just ordinary methods.
|
||||||
|
impl<'tcx> Builder<'_, '_, 'tcx> {
|
||||||
|
/// Returns true if the function source hash was added to the coverage map (even if it had
|
||||||
|
/// already been added, for this instance). Returns false *only* if `-C instrument-coverage` is
|
||||||
|
/// not enabled (a coverage map is not being generated).
|
||||||
fn set_function_source_hash(
|
fn set_function_source_hash(
|
||||||
&mut self,
|
&mut self,
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
|
@ -115,6 +172,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the counter was added to the coverage map; false if `-C instrument-coverage`
|
||||||
|
/// is not enabled (a coverage map is not being generated).
|
||||||
fn add_coverage_counter(
|
fn add_coverage_counter(
|
||||||
&mut self,
|
&mut self,
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
|
@ -137,6 +196,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the expression was added to the coverage map; false if
|
||||||
|
/// `-C instrument-coverage` is not enabled (a coverage map is not being generated).
|
||||||
fn add_coverage_counter_expression(
|
fn add_coverage_counter_expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
|
@ -163,6 +224,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the region was added to the coverage map; false if `-C instrument-coverage`
|
||||||
|
/// is not enabled (a coverage map is not being generated).
|
||||||
fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool {
|
fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool {
|
||||||
if let Some(coverage_context) = self.coverage_context() {
|
if let Some(coverage_context) = self.coverage_context() {
|
||||||
debug!(
|
debug!(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
use rustc_codegen_ssa::coverageinfo::map as coverage_map;
|
use crate::coverageinfo::map_data as coverage_map;
|
||||||
|
|
||||||
use super::debuginfo::{
|
use super::debuginfo::{
|
||||||
DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator,
|
DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator,
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
pub mod ffi;
|
|
||||||
pub mod map;
|
|
|
@ -48,7 +48,6 @@ pub mod back;
|
||||||
pub mod base;
|
pub mod base;
|
||||||
pub mod codegen_attrs;
|
pub mod codegen_attrs;
|
||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod coverageinfo;
|
|
||||||
pub mod debuginfo;
|
pub mod debuginfo;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod glue;
|
pub mod glue;
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
|
|
||||||
use rustc_middle::mir::coverage::*;
|
|
||||||
use rustc_middle::mir::Coverage;
|
use rustc_middle::mir::Coverage;
|
||||||
use rustc_middle::mir::SourceScope;
|
use rustc_middle::mir::SourceScope;
|
||||||
|
|
||||||
use super::FunctionCx;
|
use super::FunctionCx;
|
||||||
|
|
||||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) {
|
pub fn codegen_coverage(&self, bx: &mut Bx, coverage: &Coverage, scope: SourceScope) {
|
||||||
// Determine the instance that coverage data was originally generated for.
|
// Determine the instance that coverage data was originally generated for.
|
||||||
let instance = if let Some(inlined) = scope.inlined_instance(&self.mir.source_scopes) {
|
let instance = if let Some(inlined) = scope.inlined_instance(&self.mir.source_scopes) {
|
||||||
self.monomorphize(inlined)
|
self.monomorphize(inlined)
|
||||||
|
@ -15,41 +14,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
self.instance
|
self.instance
|
||||||
};
|
};
|
||||||
|
|
||||||
let Coverage { kind, code_region } = coverage;
|
// Handle the coverage info in a backend-specific way.
|
||||||
match kind {
|
bx.add_coverage(instance, coverage);
|
||||||
CoverageKind::Counter { function_source_hash, id } => {
|
|
||||||
if bx.set_function_source_hash(instance, function_source_hash) {
|
|
||||||
// If `set_function_source_hash()` returned true, the coverage map is enabled,
|
|
||||||
// so continue adding the counter.
|
|
||||||
if let Some(code_region) = code_region {
|
|
||||||
// Note: Some counters do not have code regions, but may still be referenced
|
|
||||||
// from expressions. In that case, don't add the counter to the coverage map,
|
|
||||||
// but do inject the counter intrinsic.
|
|
||||||
bx.add_coverage_counter(instance, id, code_region);
|
|
||||||
}
|
|
||||||
|
|
||||||
let coverageinfo = bx.tcx().coverageinfo(instance.def);
|
|
||||||
|
|
||||||
let fn_name = bx.get_pgo_func_name_var(instance);
|
|
||||||
let hash = bx.const_u64(function_source_hash);
|
|
||||||
let num_counters = bx.const_u32(coverageinfo.num_counters);
|
|
||||||
let index = bx.const_u32(id.zero_based_index());
|
|
||||||
debug!(
|
|
||||||
"codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
|
|
||||||
fn_name, hash, num_counters, index,
|
|
||||||
);
|
|
||||||
bx.instrprof_increment(fn_name, hash, num_counters, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CoverageKind::Expression { id, lhs, op, rhs } => {
|
|
||||||
bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region);
|
|
||||||
}
|
|
||||||
CoverageKind::Unreachable => {
|
|
||||||
bx.add_coverage_unreachable(
|
|
||||||
instance,
|
|
||||||
code_region.expect("unreachable regions always have code regions"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::StatementKind::Coverage(box ref coverage) => {
|
mir::StatementKind::Coverage(box ref coverage) => {
|
||||||
self.codegen_coverage(bx, coverage.clone(), statement.source_info.scope);
|
self.codegen_coverage(bx, coverage, statement.source_info.scope);
|
||||||
}
|
}
|
||||||
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => {
|
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => {
|
||||||
let op_val = self.codegen_operand(bx, op);
|
let op_val = self.codegen_operand(bx, op);
|
||||||
|
|
|
@ -1,57 +1,11 @@
|
||||||
use super::BackendTypes;
|
use super::BackendTypes;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_middle::mir::Coverage;
|
||||||
use rustc_middle::mir::coverage::*;
|
|
||||||
use rustc_middle::ty::Instance;
|
use rustc_middle::ty::Instance;
|
||||||
|
|
||||||
pub trait CoverageInfoMethods<'tcx>: BackendTypes {
|
|
||||||
fn coverageinfo_finalize(&self);
|
|
||||||
|
|
||||||
/// Codegen a small function that will never be called, with one counter
|
|
||||||
/// that will never be incremented, that gives LLVM coverage tools a
|
|
||||||
/// function definition it needs in order to resolve coverage map references
|
|
||||||
/// to unused functions. This is necessary so unused functions will appear
|
|
||||||
/// as uncovered (coverage execution count `0`) in LLVM coverage reports.
|
|
||||||
fn define_unused_fn(&self, def_id: DefId);
|
|
||||||
|
|
||||||
/// For LLVM codegen, returns a function-specific `Value` for a global
|
|
||||||
/// string, to hold the function name passed to LLVM intrinsic
|
|
||||||
/// `instrprof.increment()`. The `Value` is only created once per instance.
|
|
||||||
/// Multiple invocations with the same instance return the same `Value`.
|
|
||||||
fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
|
pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
|
||||||
/// Returns true if the function source hash was added to the coverage map (even if it had
|
/// Handle the MIR coverage info in a backend-specific way.
|
||||||
/// already been added, for this instance). Returns false *only* if `-C instrument-coverage` is
|
///
|
||||||
/// not enabled (a coverage map is not being generated).
|
/// This can potentially be a no-op in backends that don't support
|
||||||
fn set_function_source_hash(
|
/// coverage instrumentation.
|
||||||
&mut self,
|
fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage);
|
||||||
instance: Instance<'tcx>,
|
|
||||||
function_source_hash: u64,
|
|
||||||
) -> bool;
|
|
||||||
|
|
||||||
/// Returns true if the counter was added to the coverage map; false if `-C instrument-coverage`
|
|
||||||
/// is not enabled (a coverage map is not being generated).
|
|
||||||
fn add_coverage_counter(
|
|
||||||
&mut self,
|
|
||||||
instance: Instance<'tcx>,
|
|
||||||
index: CounterValueReference,
|
|
||||||
region: CodeRegion,
|
|
||||||
) -> bool;
|
|
||||||
|
|
||||||
/// Returns true if the expression was added to the coverage map; false if
|
|
||||||
/// `-C instrument-coverage` is not enabled (a coverage map is not being generated).
|
|
||||||
fn add_coverage_counter_expression(
|
|
||||||
&mut self,
|
|
||||||
instance: Instance<'tcx>,
|
|
||||||
id: InjectedExpressionId,
|
|
||||||
lhs: ExpressionOperandId,
|
|
||||||
op: Op,
|
|
||||||
rhs: ExpressionOperandId,
|
|
||||||
region: Option<CodeRegion>,
|
|
||||||
) -> bool;
|
|
||||||
|
|
||||||
/// Returns true if the region was added to the coverage map; false if `-C instrument-coverage`
|
|
||||||
/// is not enabled (a coverage map is not being generated).
|
|
||||||
fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAs
|
||||||
pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods};
|
pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods};
|
||||||
pub use self::builder::{BuilderMethods, OverflowOp};
|
pub use self::builder::{BuilderMethods, OverflowOp};
|
||||||
pub use self::consts::ConstMethods;
|
pub use self::consts::ConstMethods;
|
||||||
pub use self::coverageinfo::{CoverageInfoBuilderMethods, CoverageInfoMethods};
|
pub use self::coverageinfo::CoverageInfoBuilderMethods;
|
||||||
pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
|
pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
|
||||||
pub use self::declare::PreDefineMethods;
|
pub use self::declare::PreDefineMethods;
|
||||||
pub use self::intrinsic::IntrinsicCallMethods;
|
pub use self::intrinsic::IntrinsicCallMethods;
|
||||||
|
@ -59,7 +59,6 @@ pub trait CodegenMethods<'tcx>:
|
||||||
+ MiscMethods<'tcx>
|
+ MiscMethods<'tcx>
|
||||||
+ ConstMethods<'tcx>
|
+ ConstMethods<'tcx>
|
||||||
+ StaticMethods
|
+ StaticMethods
|
||||||
+ CoverageInfoMethods<'tcx>
|
|
||||||
+ DebugInfoMethods<'tcx>
|
+ DebugInfoMethods<'tcx>
|
||||||
+ AsmMethods<'tcx>
|
+ AsmMethods<'tcx>
|
||||||
+ PreDefineMethods<'tcx>
|
+ PreDefineMethods<'tcx>
|
||||||
|
@ -75,7 +74,6 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
|
||||||
+ MiscMethods<'tcx>
|
+ MiscMethods<'tcx>
|
||||||
+ ConstMethods<'tcx>
|
+ ConstMethods<'tcx>
|
||||||
+ StaticMethods
|
+ StaticMethods
|
||||||
+ CoverageInfoMethods<'tcx>
|
|
||||||
+ DebugInfoMethods<'tcx>
|
+ DebugInfoMethods<'tcx>
|
||||||
+ AsmMethods<'tcx>
|
+ AsmMethods<'tcx>
|
||||||
+ PreDefineMethods<'tcx>
|
+ PreDefineMethods<'tcx>
|
||||||
|
|
|
@ -254,7 +254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
type BreakTy = ty::GenericArg<'tcx>;
|
type BreakTy = ty::GenericArg<'tcx>;
|
||||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
|
||||||
if let Some(origin) = self.0.type_var_origin(ty)
|
if let Some(origin) = self.0.type_var_origin(ty)
|
||||||
&& let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) =
|
&& let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, def_id) =
|
||||||
origin.kind
|
origin.kind
|
||||||
&& let generics = self.0.tcx.generics_of(self.1)
|
&& let generics = self.0.tcx.generics_of(self.1)
|
||||||
&& let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
|
&& let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
|
||||||
|
|
|
@ -265,9 +265,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
kind: UnderspecifiedArgKind::Type {
|
kind: UnderspecifiedArgKind::Type {
|
||||||
prefix: "type parameter".into(),
|
prefix: "type parameter".into(),
|
||||||
},
|
},
|
||||||
parent: def_id.and_then(|def_id| {
|
parent: InferenceDiagnosticsParentData::for_def_id(
|
||||||
InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id)
|
self.tcx, def_id,
|
||||||
}),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1110,7 +1110,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
TypeVariableOrigin {
|
TypeVariableOrigin {
|
||||||
kind: TypeVariableOriginKind::TypeParameterDefinition(
|
kind: TypeVariableOriginKind::TypeParameterDefinition(
|
||||||
param.name,
|
param.name,
|
||||||
Some(param.def_id),
|
param.def_id,
|
||||||
),
|
),
|
||||||
span,
|
span,
|
||||||
},
|
},
|
||||||
|
|
|
@ -21,23 +21,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
recursion_depth: usize,
|
recursion_depth: usize,
|
||||||
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
if self.next_trait_solver() {
|
debug_assert!(!self.next_trait_solver());
|
||||||
// FIXME(-Ztrait-solver=next): Instead of branching here,
|
|
||||||
// completely change the normalization routine with the new solver.
|
|
||||||
//
|
|
||||||
// The new solver correctly handles projection equality so this hack
|
|
||||||
// is not necessary. if re-enabled it should emit `PredicateKind::AliasRelate`
|
|
||||||
// not `PredicateKind::Clause(ClauseKind::Projection(..))` as in the new solver
|
|
||||||
// `Projection` is used as `normalizes-to` which will fail for `<T as Trait>::Assoc eq ?0`.
|
|
||||||
return projection_ty.to_ty(self.tcx);
|
|
||||||
} else {
|
|
||||||
let def_id = projection_ty.def_id;
|
let def_id = projection_ty.def_id;
|
||||||
let ty_var = self.next_ty_var(TypeVariableOrigin {
|
let ty_var = self.next_ty_var(TypeVariableOrigin {
|
||||||
kind: TypeVariableOriginKind::NormalizeProjectionType,
|
kind: TypeVariableOriginKind::NormalizeProjectionType,
|
||||||
span: self.tcx.def_span(def_id),
|
span: self.tcx.def_span(def_id),
|
||||||
});
|
});
|
||||||
let projection =
|
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection(
|
||||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection(
|
|
||||||
ty::ProjectionPredicate { projection_ty, term: ty_var.into() },
|
ty::ProjectionPredicate { projection_ty, term: ty_var.into() },
|
||||||
)));
|
)));
|
||||||
let obligation =
|
let obligation =
|
||||||
|
@ -45,5 +35,4 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
obligations.push(obligation);
|
obligations.push(obligation);
|
||||||
ty_var
|
ty_var
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ pub enum TypeVariableOriginKind {
|
||||||
NormalizeProjectionType,
|
NormalizeProjectionType,
|
||||||
TypeInference,
|
TypeInference,
|
||||||
OpaqueTypeInference(DefId),
|
OpaqueTypeInference(DefId),
|
||||||
TypeParameterDefinition(Symbol, Option<DefId>),
|
TypeParameterDefinition(Symbol, DefId),
|
||||||
|
|
||||||
/// One of the upvars or closure kind parameters in a `ClosureSubsts`
|
/// One of the upvars or closure kind parameters in a `ClosureSubsts`
|
||||||
/// (before it has been determined).
|
/// (before it has been determined).
|
||||||
|
|
|
@ -2329,7 +2329,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
|
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Ty(c) => {
|
Self::Ty(c) => {
|
||||||
if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) {
|
if let Some(val) = c.try_eval_for_mir(tcx, param_env) {
|
||||||
match val {
|
match val {
|
||||||
Ok(val) => Self::Val(val, c.ty()),
|
Ok(val) => Self::Val(val, c.ty()),
|
||||||
Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())),
|
Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())),
|
||||||
|
@ -2867,7 +2867,7 @@ fn pretty_print_const_value<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
|
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
|
||||||
let n = n.kind().try_to_bits(tcx.data_layout.pointer_size).unwrap();
|
let n = n.try_to_bits(tcx.data_layout.pointer_size).unwrap();
|
||||||
// cast is ok because we already checked for pointer size (32 or 64 bit) above
|
// cast is ok because we already checked for pointer size (32 or 64 bit) above
|
||||||
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
|
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
|
||||||
let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();
|
let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();
|
||||||
|
|
|
@ -588,6 +588,10 @@ pub enum SelectionError<'tcx> {
|
||||||
/// Signaling that an error has already been emitted, to avoid
|
/// Signaling that an error has already been emitted, to avoid
|
||||||
/// multiple errors being shown.
|
/// multiple errors being shown.
|
||||||
ErrorReporting,
|
ErrorReporting,
|
||||||
|
/// Computing an opaque type's hidden type caused an error (e.g. a cycle error).
|
||||||
|
/// We can thus not know whether the hidden type implements an auto trait, so
|
||||||
|
/// we should not presume anything about it.
|
||||||
|
OpaqueTypeAutoTraitLeakageUnknown(DefId),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, TypeVisitable, Lift)]
|
#[derive(Clone, Debug, TypeVisitable, Lift)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::middle::resolve_bound_vars as rbv;
|
use crate::middle::resolve_bound_vars as rbv;
|
||||||
use crate::mir::interpret::LitToConstInput;
|
use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar};
|
||||||
use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
|
use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_error_messages::MultiSpan;
|
use rustc_error_messages::MultiSpan;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -14,9 +14,13 @@ mod valtree;
|
||||||
|
|
||||||
pub use int::*;
|
pub use int::*;
|
||||||
pub use kind::*;
|
pub use kind::*;
|
||||||
|
use rustc_span::ErrorGuaranteed;
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
|
use rustc_target::abi::Size;
|
||||||
pub use valtree::*;
|
pub use valtree::*;
|
||||||
|
|
||||||
|
use super::sty::ConstKind;
|
||||||
|
|
||||||
/// Use this rather than `ConstData`, whenever possible.
|
/// Use this rather than `ConstData`, whenever possible.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
|
||||||
#[rustc_pass_by_value]
|
#[rustc_pass_by_value]
|
||||||
|
@ -32,6 +36,16 @@ pub struct ConstData<'tcx> {
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
static_assert_size!(ConstData<'_>, 40);
|
static_assert_size!(ConstData<'_>, 40);
|
||||||
|
|
||||||
|
enum EvalMode {
|
||||||
|
Typeck,
|
||||||
|
Mir,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EvalResult<'tcx> {
|
||||||
|
ValTree(ty::ValTree<'tcx>),
|
||||||
|
ConstVal(ConstValue<'tcx>),
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Const<'tcx> {
|
impl<'tcx> Const<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn ty(self) -> Ty<'tcx> {
|
pub fn ty(self) -> Ty<'tcx> {
|
||||||
|
@ -40,7 +54,7 @@ impl<'tcx> Const<'tcx> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn kind(self) -> ConstKind<'tcx> {
|
pub fn kind(self) -> ConstKind<'tcx> {
|
||||||
self.0.kind
|
self.0.kind.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -293,12 +307,12 @@ impl<'tcx> Const<'tcx> {
|
||||||
assert_eq!(self.ty(), ty);
|
assert_eq!(self.ty(), ty);
|
||||||
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
|
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
|
||||||
// if `ty` does not depend on generic parameters, use an empty param_env
|
// if `ty` does not depend on generic parameters, use an empty param_env
|
||||||
self.kind().eval(tcx, param_env).try_to_bits(size)
|
self.eval(tcx, param_env).try_to_bits(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
|
pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
|
||||||
self.kind().eval(tcx, param_env).try_to_bool()
|
self.eval(tcx, param_env).try_to_bool()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -307,14 +321,14 @@ impl<'tcx> Const<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
) -> Option<u64> {
|
) -> Option<u64> {
|
||||||
self.kind().eval(tcx, param_env).try_to_target_usize(tcx)
|
self.eval(tcx, param_env).try_to_target_usize(tcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
|
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
|
||||||
/// unevaluated constant.
|
/// unevaluated constant.
|
||||||
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
|
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
|
||||||
if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
|
if let Some(val) = self.try_eval_for_typeck(tcx, param_env) {
|
||||||
match val {
|
match val {
|
||||||
Ok(val) => ty::Const::new_value(tcx, val, self.ty()),
|
Ok(val) => ty::Const::new_value(tcx, val, self.ty()),
|
||||||
Err(guar) => ty::Const::new_error(tcx, guar, self.ty()),
|
Err(guar) => ty::Const::new_error(tcx, guar, self.ty()),
|
||||||
|
@ -339,6 +353,138 @@ impl<'tcx> Const<'tcx> {
|
||||||
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
|
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
|
||||||
|
/// return `None`.
|
||||||
|
// FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
|
||||||
|
pub fn try_eval_for_mir(
|
||||||
|
self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
param_env: ParamEnv<'tcx>,
|
||||||
|
) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
|
||||||
|
match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
|
||||||
|
Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
|
||||||
|
Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
|
||||||
|
Some(Err(e)) => Some(Err(e)),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
|
||||||
|
/// return `None`.
|
||||||
|
// FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
|
||||||
|
pub fn try_eval_for_typeck(
|
||||||
|
self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
param_env: ParamEnv<'tcx>,
|
||||||
|
) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
|
||||||
|
match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
|
||||||
|
Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
|
||||||
|
Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
|
||||||
|
Some(Err(e)) => Some(Err(e)),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn try_eval_inner(
|
||||||
|
self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
param_env: ParamEnv<'tcx>,
|
||||||
|
eval_mode: EvalMode,
|
||||||
|
) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
|
||||||
|
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
|
||||||
|
if let ConstKind::Unevaluated(unevaluated) = self.kind() {
|
||||||
|
use crate::mir::interpret::ErrorHandled;
|
||||||
|
|
||||||
|
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
|
||||||
|
// also does later, but we want to do it before checking for
|
||||||
|
// inference variables.
|
||||||
|
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
|
||||||
|
// so that we don't try to invoke this query with
|
||||||
|
// any region variables.
|
||||||
|
|
||||||
|
// HACK(eddyb) when the query key would contain inference variables,
|
||||||
|
// attempt using identity substs and `ParamEnv` instead, that will succeed
|
||||||
|
// when the expression doesn't depend on any parameters.
|
||||||
|
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
|
||||||
|
// we can call `infcx.const_eval_resolve` which handles inference variables.
|
||||||
|
let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
|
||||||
|
tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
|
||||||
|
def: unevaluated.def,
|
||||||
|
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
tcx.erase_regions(param_env)
|
||||||
|
.with_reveal_all_normalized(tcx)
|
||||||
|
.and(tcx.erase_regions(unevaluated))
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME(eddyb) maybe the `const_eval_*` methods should take
|
||||||
|
// `ty::ParamEnvAnd` instead of having them separate.
|
||||||
|
let (param_env, unevaluated) = param_env_and.into_parts();
|
||||||
|
// try to resolve e.g. associated constants to their definition on an impl, and then
|
||||||
|
// evaluate the const.
|
||||||
|
match eval_mode {
|
||||||
|
EvalMode::Typeck => {
|
||||||
|
match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
|
||||||
|
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
|
||||||
|
// and we use the original type, so nothing from `substs`
|
||||||
|
// (which may be identity substs, see above),
|
||||||
|
// can leak through `val` into the const we return.
|
||||||
|
Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
|
||||||
|
Err(ErrorHandled::TooGeneric) => None,
|
||||||
|
Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EvalMode::Mir => {
|
||||||
|
match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
|
||||||
|
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
|
||||||
|
// and we use the original type, so nothing from `substs`
|
||||||
|
// (which may be identity substs, see above),
|
||||||
|
// can leak through `val` into the const we return.
|
||||||
|
Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
|
||||||
|
Err(ErrorHandled::TooGeneric) => None,
|
||||||
|
Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
|
||||||
|
if let ConstKind::Value(val) = self.kind() { Some(val) } else { None }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
|
||||||
|
self.try_to_value()?.try_to_scalar()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
|
||||||
|
self.try_to_value()?.try_to_scalar_int()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn try_to_bits(self, size: Size) -> Option<u128> {
|
||||||
|
self.try_to_scalar_int()?.to_bits(size).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn try_to_bool(self) -> Option<bool> {
|
||||||
|
self.try_to_scalar_int()?.try_into().ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
|
||||||
|
self.try_to_value()?.try_to_target_usize(tcx)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_ct_infer(self) -> bool {
|
pub fn is_ct_infer(self) -> bool {
|
||||||
matches!(self.kind(), ty::ConstKind::Infer(_))
|
matches!(self.kind(), ty::ConstKind::Infer(_))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,11 @@
|
||||||
use super::Const;
|
use super::Const;
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
use crate::mir::interpret::{AllocId, ConstValue, Scalar};
|
|
||||||
use crate::ty::abstract_const::CastKind;
|
use crate::ty::abstract_const::CastKind;
|
||||||
use crate::ty::subst::{InternalSubsts, SubstsRef};
|
use crate::ty::subst::SubstsRef;
|
||||||
use crate::ty::ParamEnv;
|
use crate::ty::{self, List, Ty};
|
||||||
use crate::ty::{self, List, Ty, TyCtxt, TypeVisitableExt};
|
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_errors::ErrorGuaranteed;
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_target::abi::Size;
|
|
||||||
|
|
||||||
use super::ScalarInt;
|
|
||||||
|
|
||||||
/// An unevaluated (potentially generic) constant used in the type-system.
|
/// An unevaluated (potentially generic) constant used in the type-system.
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
|
||||||
|
@ -41,45 +35,6 @@ impl<'tcx> UnevaluatedConst<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a constant in Rust.
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
|
|
||||||
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
|
|
||||||
#[derive(derive_more::From)]
|
|
||||||
pub enum ConstKind<'tcx> {
|
|
||||||
/// A const generic parameter.
|
|
||||||
Param(ty::ParamConst),
|
|
||||||
|
|
||||||
/// Infer the value of the const.
|
|
||||||
Infer(InferConst<'tcx>),
|
|
||||||
|
|
||||||
/// Bound const variable, used only when preparing a trait query.
|
|
||||||
Bound(ty::DebruijnIndex, ty::BoundVar),
|
|
||||||
|
|
||||||
/// A placeholder const - universally quantified higher-ranked const.
|
|
||||||
Placeholder(ty::PlaceholderConst<'tcx>),
|
|
||||||
|
|
||||||
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
|
|
||||||
/// variants when the code is monomorphic enough for that.
|
|
||||||
Unevaluated(UnevaluatedConst<'tcx>),
|
|
||||||
|
|
||||||
/// Used to hold computed value.
|
|
||||||
Value(ty::ValTree<'tcx>),
|
|
||||||
|
|
||||||
/// A placeholder for a const which could not be computed; this is
|
|
||||||
/// propagated to avoid useless error messages.
|
|
||||||
#[from(ignore)]
|
|
||||||
Error(ErrorGuaranteed),
|
|
||||||
|
|
||||||
/// Expr which contains an expression which has partially evaluated items.
|
|
||||||
Expr(Expr<'tcx>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> From<ty::ConstVid<'tcx>> for ConstKind<'tcx> {
|
|
||||||
fn from(const_vid: ty::ConstVid<'tcx>) -> Self {
|
|
||||||
InferConst::Var(const_vid).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||||
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
|
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
|
||||||
pub enum Expr<'tcx> {
|
pub enum Expr<'tcx> {
|
||||||
|
@ -93,39 +48,7 @@ pub enum Expr<'tcx> {
|
||||||
static_assert_size!(Expr<'_>, 24);
|
static_assert_size!(Expr<'_>, 24);
|
||||||
|
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
static_assert_size!(ConstKind<'_>, 32);
|
static_assert_size!(super::ConstKind<'_>, 32);
|
||||||
|
|
||||||
impl<'tcx> ConstKind<'tcx> {
|
|
||||||
#[inline]
|
|
||||||
pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
|
|
||||||
if let ConstKind::Value(val) = self { Some(val) } else { None }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
|
|
||||||
self.try_to_value()?.try_to_scalar()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
|
|
||||||
self.try_to_value()?.try_to_scalar_int()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn try_to_bits(self, size: Size) -> Option<u128> {
|
|
||||||
self.try_to_scalar_int()?.to_bits(size).ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn try_to_bool(self) -> Option<bool> {
|
|
||||||
self.try_to_scalar_int()?.try_into().ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
|
|
||||||
self.try_to_value()?.try_to_target_usize(tcx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An inference variable for a const, for use in const generics.
|
/// An inference variable for a const, for use in const generics.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
|
||||||
|
@ -144,124 +67,3 @@ impl<CTX> HashStable<CTX> for InferConst<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EvalMode {
|
|
||||||
Typeck,
|
|
||||||
Mir,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum EvalResult<'tcx> {
|
|
||||||
ValTree(ty::ValTree<'tcx>),
|
|
||||||
ConstVal(ConstValue<'tcx>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> ConstKind<'tcx> {
|
|
||||||
#[inline]
|
|
||||||
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
|
|
||||||
/// unevaluated constant.
|
|
||||||
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
|
|
||||||
self.try_eval_for_typeck(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
|
|
||||||
/// return `None`.
|
|
||||||
// FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
|
|
||||||
pub fn try_eval_for_mir(
|
|
||||||
self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
param_env: ParamEnv<'tcx>,
|
|
||||||
) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
|
|
||||||
match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
|
|
||||||
Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
|
|
||||||
Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
|
|
||||||
Some(Err(e)) => Some(Err(e)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
|
|
||||||
/// return `None`.
|
|
||||||
// FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
|
|
||||||
pub fn try_eval_for_typeck(
|
|
||||||
self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
param_env: ParamEnv<'tcx>,
|
|
||||||
) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
|
|
||||||
match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
|
|
||||||
Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
|
|
||||||
Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
|
|
||||||
Some(Err(e)) => Some(Err(e)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_eval_inner(
|
|
||||||
self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
param_env: ParamEnv<'tcx>,
|
|
||||||
eval_mode: EvalMode,
|
|
||||||
) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
|
|
||||||
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
|
|
||||||
if let ConstKind::Unevaluated(unevaluated) = self {
|
|
||||||
use crate::mir::interpret::ErrorHandled;
|
|
||||||
|
|
||||||
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
|
|
||||||
// also does later, but we want to do it before checking for
|
|
||||||
// inference variables.
|
|
||||||
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
|
|
||||||
// so that we don't try to invoke this query with
|
|
||||||
// any region variables.
|
|
||||||
|
|
||||||
// HACK(eddyb) when the query key would contain inference variables,
|
|
||||||
// attempt using identity substs and `ParamEnv` instead, that will succeed
|
|
||||||
// when the expression doesn't depend on any parameters.
|
|
||||||
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
|
|
||||||
// we can call `infcx.const_eval_resolve` which handles inference variables.
|
|
||||||
let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
|
|
||||||
tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
|
|
||||||
def: unevaluated.def,
|
|
||||||
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
tcx.erase_regions(param_env)
|
|
||||||
.with_reveal_all_normalized(tcx)
|
|
||||||
.and(tcx.erase_regions(unevaluated))
|
|
||||||
};
|
|
||||||
|
|
||||||
// FIXME(eddyb) maybe the `const_eval_*` methods should take
|
|
||||||
// `ty::ParamEnvAnd` instead of having them separate.
|
|
||||||
let (param_env, unevaluated) = param_env_and.into_parts();
|
|
||||||
// try to resolve e.g. associated constants to their definition on an impl, and then
|
|
||||||
// evaluate the const.
|
|
||||||
match eval_mode {
|
|
||||||
EvalMode::Typeck => {
|
|
||||||
match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
|
|
||||||
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
|
|
||||||
// and we use the original type, so nothing from `substs`
|
|
||||||
// (which may be identity substs, see above),
|
|
||||||
// can leak through `val` into the const we return.
|
|
||||||
Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
|
|
||||||
Err(ErrorHandled::TooGeneric) => None,
|
|
||||||
Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EvalMode::Mir => {
|
|
||||||
match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
|
|
||||||
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
|
|
||||||
// and we use the original type, so nothing from `substs`
|
|
||||||
// (which may be identity substs, see above),
|
|
||||||
// can leak through `val` into the const we return.
|
|
||||||
Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
|
|
||||||
Err(ErrorHandled::TooGeneric) => None,
|
|
||||||
Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -108,6 +108,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||||
type PredicateKind = ty::PredicateKind<'tcx>;
|
type PredicateKind = ty::PredicateKind<'tcx>;
|
||||||
type AllocId = crate::mir::interpret::AllocId;
|
type AllocId = crate::mir::interpret::AllocId;
|
||||||
|
|
||||||
|
type InferConst = ty::InferConst<'tcx>;
|
||||||
|
type AliasConst = ty::UnevaluatedConst<'tcx>;
|
||||||
|
type ParamConst = ty::ParamConst;
|
||||||
|
type BoundConst = ty::BoundVar;
|
||||||
|
type PlaceholderConst = ty::PlaceholderConst<'tcx>;
|
||||||
|
type ValueConst = ty::ValTree<'tcx>;
|
||||||
|
type ExprConst = ty::Expr<'tcx>;
|
||||||
|
|
||||||
type EarlyBoundRegion = ty::EarlyBoundRegion;
|
type EarlyBoundRegion = ty::EarlyBoundRegion;
|
||||||
type BoundRegion = ty::BoundRegion;
|
type BoundRegion = ty::BoundRegion;
|
||||||
type FreeRegion = ty::FreeRegion;
|
type FreeRegion = ty::FreeRegion;
|
||||||
|
|
|
@ -170,7 +170,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
|
||||||
match self {
|
match self {
|
||||||
Self::ConstIsZero(c) => {
|
Self::ConstIsZero(c) => {
|
||||||
let c = ty::EarlyBinder::bind(c).subst(tcx, substs);
|
let c = ty::EarlyBinder::bind(c).subst(tcx, substs);
|
||||||
let pred = match c.kind().try_to_target_usize(tcx) {
|
let pred = match c.try_to_target_usize(tcx) {
|
||||||
Some(0) => Self::True,
|
Some(0) => Self::True,
|
||||||
Some(1..) => Self::False,
|
Some(1..) => Self::False,
|
||||||
None => Self::ConstIsZero(c),
|
None => Self::ConstIsZero(c),
|
||||||
|
|
|
@ -197,7 +197,7 @@ fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedP
|
||||||
|
|
||||||
// If we can evaluate the array length before having a `ParamEnv`, then
|
// If we can evaluate the array length before having a `ParamEnv`, then
|
||||||
// we can simplify the predicate. This is an optimization.
|
// we can simplify the predicate. This is an optimization.
|
||||||
Array(ty, len) => match len.kind().try_to_target_usize(tcx) {
|
Array(ty, len) => match len.try_to_target_usize(tcx) {
|
||||||
Some(0) => InhabitedPredicate::True,
|
Some(0) => InhabitedPredicate::True,
|
||||||
Some(1..) => ty.inhabited_predicate(tcx),
|
Some(1..) => ty.inhabited_predicate(tcx),
|
||||||
None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)),
|
None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)),
|
||||||
|
|
|
@ -410,8 +410,8 @@ impl<'tcx> Instance<'tcx> {
|
||||||
) -> Instance<'tcx> {
|
) -> Instance<'tcx> {
|
||||||
match ty::Instance::resolve(tcx, param_env, def_id, substs) {
|
match ty::Instance::resolve(tcx, param_env, def_id, substs) {
|
||||||
Ok(Some(instance)) => instance,
|
Ok(Some(instance)) => instance,
|
||||||
_ => bug!(
|
instance => bug!(
|
||||||
"failed to resolve instance for {}",
|
"failed to resolve instance for {}: {instance:#?}",
|
||||||
tcx.def_path_str_with_substs(def_id, substs)
|
tcx.def_path_str_with_substs(def_id, substs)
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,10 @@ use std::{fmt, str};
|
||||||
|
|
||||||
pub use crate::ty::diagnostics::*;
|
pub use crate::ty::diagnostics::*;
|
||||||
pub use rustc_type_ir::AliasKind::*;
|
pub use rustc_type_ir::AliasKind::*;
|
||||||
|
pub use rustc_type_ir::ConstKind::{
|
||||||
|
Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt,
|
||||||
|
Placeholder as PlaceholderCt, Unevaluated, Value,
|
||||||
|
};
|
||||||
pub use rustc_type_ir::DynKind::*;
|
pub use rustc_type_ir::DynKind::*;
|
||||||
pub use rustc_type_ir::InferTy::*;
|
pub use rustc_type_ir::InferTy::*;
|
||||||
pub use rustc_type_ir::RegionKind::*;
|
pub use rustc_type_ir::RegionKind::*;
|
||||||
|
@ -81,7 +85,7 @@ pub use self::closure::{
|
||||||
CAPTURE_STRUCT_LOCAL,
|
CAPTURE_STRUCT_LOCAL,
|
||||||
};
|
};
|
||||||
pub use self::consts::{
|
pub use self::consts::{
|
||||||
Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
|
Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
|
||||||
};
|
};
|
||||||
pub use self::context::{
|
pub use self::context::{
|
||||||
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
|
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
|
||||||
|
@ -93,7 +97,7 @@ pub use self::rvalue_scopes::RvalueScopes;
|
||||||
pub use self::sty::BoundRegionKind::*;
|
pub use self::sty::BoundRegionKind::*;
|
||||||
pub use self::sty::{
|
pub use self::sty::{
|
||||||
AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
|
AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
|
||||||
BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
|
BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstKind, ConstVid,
|
||||||
EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
|
EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
|
||||||
FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
|
FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
|
||||||
InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
|
InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
|
||||||
use rustc_hir::def::Namespace;
|
use rustc_hir::def::Namespace;
|
||||||
use rustc_index::{Idx, IndexVec};
|
use rustc_index::{Idx, IndexVec};
|
||||||
use rustc_target::abi::TyAndLayout;
|
use rustc_target::abi::TyAndLayout;
|
||||||
|
use rustc_type_ir::ConstKind;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
@ -241,24 +242,6 @@ impl<'tcx> fmt::Debug for ty::Const<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for ty::ConstKind<'tcx> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
use ty::ConstKind::*;
|
|
||||||
match self {
|
|
||||||
Param(param) => write!(f, "{param:?}"),
|
|
||||||
Infer(var) => write!(f, "{var:?}"),
|
|
||||||
Bound(debruijn, var) => rustc_type_ir::debug_bound_var(f, *debruijn, *var),
|
|
||||||
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
|
|
||||||
Unevaluated(uv) => {
|
|
||||||
f.debug_tuple("Unevaluated").field(&uv.substs).field(&uv.def).finish()
|
|
||||||
}
|
|
||||||
Value(valtree) => write!(f, "{valtree:?}"),
|
|
||||||
Error(_) => write!(f, "{{const error}}"),
|
|
||||||
Expr(expr) => write!(f, "{expr:?}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for ty::BoundTy {
|
impl fmt::Debug for ty::BoundTy {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
|
@ -728,7 +711,18 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
||||||
folder: &mut F,
|
folder: &mut F,
|
||||||
) -> Result<Self, F::Error> {
|
) -> Result<Self, F::Error> {
|
||||||
let ty = self.ty().try_fold_with(folder)?;
|
let ty = self.ty().try_fold_with(folder)?;
|
||||||
let kind = self.kind().try_fold_with(folder)?;
|
let kind = match self.kind() {
|
||||||
|
ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?),
|
||||||
|
ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?),
|
||||||
|
ConstKind::Bound(d, b) => {
|
||||||
|
ConstKind::Bound(d.try_fold_with(folder)?, b.try_fold_with(folder)?)
|
||||||
|
}
|
||||||
|
ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?),
|
||||||
|
ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?),
|
||||||
|
ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?),
|
||||||
|
ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?),
|
||||||
|
ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
|
||||||
|
};
|
||||||
if ty != self.ty() || kind != self.kind() {
|
if ty != self.ty() || kind != self.kind() {
|
||||||
Ok(folder.interner().mk_ct_from_kind(kind, ty))
|
Ok(folder.interner().mk_ct_from_kind(kind, ty))
|
||||||
} else {
|
} else {
|
||||||
|
@ -743,7 +737,19 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
||||||
visitor: &mut V,
|
visitor: &mut V,
|
||||||
) -> ControlFlow<V::BreakTy> {
|
) -> ControlFlow<V::BreakTy> {
|
||||||
self.ty().visit_with(visitor)?;
|
self.ty().visit_with(visitor)?;
|
||||||
self.kind().visit_with(visitor)
|
match self.kind() {
|
||||||
|
ConstKind::Param(p) => p.visit_with(visitor),
|
||||||
|
ConstKind::Infer(i) => i.visit_with(visitor),
|
||||||
|
ConstKind::Bound(d, b) => {
|
||||||
|
d.visit_with(visitor)?;
|
||||||
|
b.visit_with(visitor)
|
||||||
|
}
|
||||||
|
ConstKind::Placeholder(p) => p.visit_with(visitor),
|
||||||
|
ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
|
||||||
|
ConstKind::Value(v) => v.visit_with(visitor),
|
||||||
|
ConstKind::Error(e) => e.visit_with(visitor),
|
||||||
|
ConstKind::Expr(e) => e.visit_with(visitor),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ use std::ops::{ControlFlow, Deref, Range};
|
||||||
use ty::util::IntTypeExt;
|
use ty::util::IntTypeExt;
|
||||||
|
|
||||||
use rustc_type_ir::sty::TyKind::*;
|
use rustc_type_ir::sty::TyKind::*;
|
||||||
|
use rustc_type_ir::ConstKind as IrConstKind;
|
||||||
use rustc_type_ir::RegionKind as IrRegionKind;
|
use rustc_type_ir::RegionKind as IrRegionKind;
|
||||||
use rustc_type_ir::TyKind as IrTyKind;
|
use rustc_type_ir::TyKind as IrTyKind;
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ use rustc_type_ir::TyKind as IrTyKind;
|
||||||
#[rustc_diagnostic_item = "TyKind"]
|
#[rustc_diagnostic_item = "TyKind"]
|
||||||
pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>;
|
pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>;
|
||||||
pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>;
|
pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>;
|
||||||
|
pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>;
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
||||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||||
|
|
|
@ -1306,7 +1306,7 @@ pub fn needs_drop_components<'tcx>(
|
||||||
ty::Array(elem_ty, size) => {
|
ty::Array(elem_ty, size) => {
|
||||||
match needs_drop_components(*elem_ty, target_layout) {
|
match needs_drop_components(*elem_ty, target_layout) {
|
||||||
Ok(v) if v.is_empty() => Ok(v),
|
Ok(v) if v.is_empty() => Ok(v),
|
||||||
res => match size.kind().try_to_bits(target_layout.pointer_size) {
|
res => match size.try_to_bits(target_layout.pointer_size) {
|
||||||
// Arrays of size zero don't need drop, even if their element
|
// Arrays of size zero don't need drop, even if their element
|
||||||
// type does.
|
// type does.
|
||||||
Some(0) => Ok(SmallVec::new()),
|
Some(0) => Ok(SmallVec::new()),
|
||||||
|
|
|
@ -126,18 +126,13 @@ where
|
||||||
|
|
||||||
#[cold]
|
#[cold]
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn mk_cycle<Q, Qcx>(
|
fn mk_cycle<Q, Qcx>(query: Q, qcx: Qcx, cycle_error: CycleError<Qcx::DepKind>) -> Q::Value
|
||||||
query: Q,
|
|
||||||
qcx: Qcx,
|
|
||||||
cycle_error: CycleError<Qcx::DepKind>,
|
|
||||||
handler: HandleCycleError,
|
|
||||||
) -> Q::Value
|
|
||||||
where
|
where
|
||||||
Q: QueryConfig<Qcx>,
|
Q: QueryConfig<Qcx>,
|
||||||
Qcx: QueryContext,
|
Qcx: QueryContext,
|
||||||
{
|
{
|
||||||
let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
|
let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
|
||||||
handle_cycle_error(query, qcx, &cycle_error, error, handler)
|
handle_cycle_error(query, qcx, &cycle_error, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_cycle_error<Q, Qcx>(
|
fn handle_cycle_error<Q, Qcx>(
|
||||||
|
@ -145,14 +140,13 @@ fn handle_cycle_error<Q, Qcx>(
|
||||||
qcx: Qcx,
|
qcx: Qcx,
|
||||||
cycle_error: &CycleError<Qcx::DepKind>,
|
cycle_error: &CycleError<Qcx::DepKind>,
|
||||||
mut error: DiagnosticBuilder<'_, ErrorGuaranteed>,
|
mut error: DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||||
handler: HandleCycleError,
|
|
||||||
) -> Q::Value
|
) -> Q::Value
|
||||||
where
|
where
|
||||||
Q: QueryConfig<Qcx>,
|
Q: QueryConfig<Qcx>,
|
||||||
Qcx: QueryContext,
|
Qcx: QueryContext,
|
||||||
{
|
{
|
||||||
use HandleCycleError::*;
|
use HandleCycleError::*;
|
||||||
match handler {
|
match query.handle_cycle_error() {
|
||||||
Error => {
|
Error => {
|
||||||
error.emit();
|
error.emit();
|
||||||
query.value_from_cycle_error(*qcx.dep_context(), &cycle_error.cycle)
|
query.value_from_cycle_error(*qcx.dep_context(), &cycle_error.cycle)
|
||||||
|
@ -277,7 +271,7 @@ where
|
||||||
&qcx.current_query_job(),
|
&qcx.current_query_job(),
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
(mk_cycle(query, qcx, error, query.handle_cycle_error()), None)
|
(mk_cycle(query, qcx, error), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -314,7 +308,7 @@ where
|
||||||
|
|
||||||
(v, Some(index))
|
(v, Some(index))
|
||||||
}
|
}
|
||||||
Err(cycle) => (mk_cycle(query, qcx, cycle, query.handle_cycle_error()), None),
|
Err(cycle) => (mk_cycle(query, qcx, cycle), None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,13 @@ pub trait Value<Tcx: DepContext, D: DepKind>: Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Tcx: DepContext, T, D: DepKind> Value<Tcx, D> for T {
|
impl<Tcx: DepContext, T, D: DepKind> Value<Tcx, D> for T {
|
||||||
default fn from_cycle_error(tcx: Tcx, _: &[QueryInfo<D>]) -> T {
|
default fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo<D>]) -> T {
|
||||||
tcx.sess().abort_if_errors();
|
tcx.sess().abort_if_errors();
|
||||||
// Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's
|
// Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's
|
||||||
// non-trivial to define it earlier.
|
// non-trivial to define it earlier.
|
||||||
panic!("Value::from_cycle_error called without errors");
|
panic!(
|
||||||
|
"<{} as Value>::from_cycle_error called without errors: {cycle:#?}",
|
||||||
|
std::any::type_name::<T>()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,7 +230,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
|
||||||
self.write_str("[")?;
|
self.write_str("[")?;
|
||||||
self = self.print_type(ty)?;
|
self = self.print_type(ty)?;
|
||||||
self.write_str("; ")?;
|
self.write_str("; ")?;
|
||||||
if let Some(size) = size.kind().try_to_bits(self.tcx().data_layout.pointer_size) {
|
if let Some(size) = size.try_to_bits(self.tcx().data_layout.pointer_size) {
|
||||||
write!(self, "{size}")?
|
write!(self, "{size}")?
|
||||||
} else if let ty::ConstKind::Param(param) = size.kind() {
|
} else if let ty::ConstKind::Param(param) = size.kind() {
|
||||||
self = param.print(self)?
|
self = param.print(self)?
|
||||||
|
|
|
@ -112,7 +112,7 @@ fn encode_const<'tcx>(
|
||||||
let _ = write!(s, "{value}");
|
let _ = write!(s, "{value}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(scalar_int) = c.kind().try_to_scalar_int() {
|
if let Some(scalar_int) = c.try_to_scalar_int() {
|
||||||
let signed = c.ty().is_signed();
|
let signed = c.ty().is_signed();
|
||||||
match scalar_int.size().bits() {
|
match scalar_int.size().bits() {
|
||||||
8 if signed => push_signed_value(&mut s, scalar_int.try_to_i8().unwrap(), 0),
|
8 if signed => push_signed_value(&mut s, scalar_int.try_to_i8().unwrap(), 0),
|
||||||
|
@ -504,8 +504,7 @@ fn encode_ty<'tcx>(
|
||||||
let _ = write!(
|
let _ = write!(
|
||||||
s,
|
s,
|
||||||
"{}",
|
"{}",
|
||||||
&len.kind()
|
&len.try_to_scalar()
|
||||||
.try_to_scalar()
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_u64()
|
.to_u64()
|
||||||
.unwrap_or_else(|_| panic!("failed to convert length to u64"))
|
.unwrap_or_else(|_| panic!("failed to convert length to u64"))
|
||||||
|
@ -815,7 +814,6 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
|
||||||
|
|
||||||
ty::Array(ty0, len) => {
|
ty::Array(ty0, len) => {
|
||||||
let len = len
|
let len = len
|
||||||
.kind()
|
|
||||||
.try_to_scalar()
|
.try_to_scalar()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_u64()
|
.to_u64()
|
||||||
|
|
|
@ -651,7 +651,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
||||||
.builtin_deref(true)
|
.builtin_deref(true)
|
||||||
.expect("tried to dereference on non-ptr type")
|
.expect("tried to dereference on non-ptr type")
|
||||||
.ty;
|
.ty;
|
||||||
// FIXME: add an assert that we only do this for valtrees.
|
// FIXME(const_generics): add an assert that we only do this for valtrees.
|
||||||
let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind(), pointee_ty);
|
let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind(), pointee_ty);
|
||||||
self = dereferenced_const.print(self)?;
|
self = dereferenced_const.print(self)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1325,6 +1325,7 @@ supported_targets! {
|
||||||
("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
|
("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
|
||||||
("i686-unknown-netbsd", i686_unknown_netbsd),
|
("i686-unknown-netbsd", i686_unknown_netbsd),
|
||||||
("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
|
("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
|
||||||
|
("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
|
||||||
("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
|
("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
|
||||||
("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
|
("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
|
||||||
|
|
||||||
|
|
19
compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs
Normal file
19
compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use crate::spec::{CodeModel, Target, TargetOptions};
|
||||||
|
|
||||||
|
pub fn target() -> Target {
|
||||||
|
Target {
|
||||||
|
llvm_target: "riscv64-unknown-netbsd".into(),
|
||||||
|
pointer_width: 64,
|
||||||
|
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
|
||||||
|
arch: "riscv64".into(),
|
||||||
|
options: TargetOptions {
|
||||||
|
code_model: Some(CodeModel::Medium),
|
||||||
|
cpu: "generic-rv64".into(),
|
||||||
|
features: "+m,+a,+f,+d,+c".into(),
|
||||||
|
llvm_abiname: "lp64d".into(),
|
||||||
|
max_atomic_width: Some(64),
|
||||||
|
mcount: "__mcount".into(),
|
||||||
|
..super::netbsd_base::opts()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,7 +52,11 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < candidates.len() {
|
while i < candidates.len() {
|
||||||
let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| {
|
let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| {
|
||||||
candidate_should_be_dropped_in_favor_of(&candidates[i], &candidates[j])
|
candidate_should_be_dropped_in_favor_of(
|
||||||
|
ecx.tcx(),
|
||||||
|
&candidates[i],
|
||||||
|
&candidates[j],
|
||||||
|
)
|
||||||
});
|
});
|
||||||
if should_drop_i {
|
if should_drop_i {
|
||||||
candidates.swap_remove(i);
|
candidates.swap_remove(i);
|
||||||
|
@ -160,12 +164,19 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn candidate_should_be_dropped_in_favor_of<'tcx>(
|
fn candidate_should_be_dropped_in_favor_of<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
victim: &Candidate<'tcx>,
|
victim: &Candidate<'tcx>,
|
||||||
other: &Candidate<'tcx>,
|
other: &Candidate<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match (victim.source, other.source) {
|
match (victim.source, other.source) {
|
||||||
(CandidateSource::ParamEnv(i), CandidateSource::ParamEnv(j)) => i >= j,
|
(CandidateSource::ParamEnv(victim_idx), CandidateSource::ParamEnv(other_idx)) => {
|
||||||
|
victim_idx >= other_idx
|
||||||
|
}
|
||||||
(_, CandidateSource::ParamEnv(_)) => true,
|
(_, CandidateSource::ParamEnv(_)) => true,
|
||||||
|
(CandidateSource::Impl(victim_def_id), CandidateSource::Impl(other_def_id)) => {
|
||||||
|
tcx.specializes((other_def_id, victim_def_id))
|
||||||
|
&& other.result.value.certainty == Certainty::Yes
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,6 +159,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
|
||||||
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
|
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
|
||||||
let reveal = self.at.param_env.reveal();
|
let reveal = self.at.param_env.reveal();
|
||||||
let infcx = self.at.infcx;
|
let infcx = self.at.infcx;
|
||||||
|
debug_assert_eq!(ty, infcx.shallow_resolve(ty));
|
||||||
if !needs_normalization(&ty, reveal) {
|
if !needs_normalization(&ty, reveal) {
|
||||||
return Ok(ty);
|
return Ok(ty);
|
||||||
}
|
}
|
||||||
|
@ -192,6 +193,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
|
||||||
fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
|
fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
|
||||||
let reveal = self.at.param_env.reveal();
|
let reveal = self.at.param_env.reveal();
|
||||||
let infcx = self.at.infcx;
|
let infcx = self.at.infcx;
|
||||||
|
debug_assert_eq!(ct, infcx.shallow_resolve(ct));
|
||||||
if !needs_normalization(&ct, reveal) {
|
if !needs_normalization(&ct, reveal) {
|
||||||
return Ok(ct);
|
return Ok(ct);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ use std::fmt::Debug;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
use super::query::evaluate_obligation::InferCtxtExt;
|
||||||
use super::NormalizeExt;
|
use super::NormalizeExt;
|
||||||
|
|
||||||
/// Whether we do the orphan check relative to this crate or
|
/// Whether we do the orphan check relative to this crate or
|
||||||
|
@ -290,6 +291,20 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>(
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let infcx = selcx.infcx;
|
let infcx = selcx.infcx;
|
||||||
|
|
||||||
|
let obligation_guaranteed_to_fail = move |obligation: &PredicateObligation<'tcx>| {
|
||||||
|
if infcx.next_trait_solver() {
|
||||||
|
infcx.evaluate_obligation(obligation).map_or(false, |result| !result.may_apply())
|
||||||
|
} else {
|
||||||
|
// We use `evaluate_root_obligation` to correctly track
|
||||||
|
// intercrate ambiguity clauses. We do not need this in the
|
||||||
|
// new solver.
|
||||||
|
selcx.evaluate_root_obligation(obligation).map_or(
|
||||||
|
false, // Overflow has occurred, and treat the obligation as possibly holding.
|
||||||
|
|result| !result.may_apply(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let opt_failing_obligation = [&impl1_header.predicates, &impl2_header.predicates]
|
let opt_failing_obligation = [&impl1_header.predicates, &impl2_header.predicates]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
|
@ -297,12 +312,7 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>(
|
||||||
Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate)
|
Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate)
|
||||||
})
|
})
|
||||||
.chain(obligations)
|
.chain(obligations)
|
||||||
.find(|o| {
|
.find(obligation_guaranteed_to_fail);
|
||||||
selcx.evaluate_root_obligation(o).map_or(
|
|
||||||
false, // Overflow has occurred, and treat the obligation as possibly holding.
|
|
||||||
|result| !result.may_apply(),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(failing_obligation) = opt_failing_obligation {
|
if let Some(failing_obligation) = opt_failing_obligation {
|
||||||
debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
|
debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
|
||||||
|
|
|
@ -30,7 +30,7 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt;
|
||||||
use rustc_infer::infer::{InferOk, TypeTrace};
|
use rustc_infer::infer::{InferOk, TypeTrace};
|
||||||
use rustc_middle::traits::select::OverflowError;
|
use rustc_middle::traits::select::OverflowError;
|
||||||
use rustc_middle::traits::solve::Goal;
|
use rustc_middle::traits::solve::Goal;
|
||||||
use rustc_middle::traits::SelectionOutputTypeParameterMismatch;
|
use rustc_middle::traits::{DefiningAnchor, SelectionOutputTypeParameterMismatch};
|
||||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||||
|
@ -1152,6 +1152,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id) => self.report_opaque_type_auto_trait_leakage(
|
||||||
|
&obligation,
|
||||||
|
def_id,
|
||||||
|
),
|
||||||
|
|
||||||
TraitNotObjectSafe(did) => {
|
TraitNotObjectSafe(did) => {
|
||||||
let violations = self.tcx.object_safety_violations(did);
|
let violations = self.tcx.object_safety_violations(did);
|
||||||
report_object_safety_error(self.tcx, span, did, violations)
|
report_object_safety_error(self.tcx, span, did, violations)
|
||||||
|
@ -1170,16 +1175,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Already reported in the query.
|
// Already reported in the query.
|
||||||
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) => {
|
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) |
|
||||||
// FIXME(eddyb) remove this once `ErrorGuaranteed` becomes a proof token.
|
|
||||||
self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Already reported.
|
// Already reported.
|
||||||
Overflow(OverflowError::Error(_)) => {
|
Overflow(OverflowError::Error(_)) => return,
|
||||||
self.tcx.sess.delay_span_bug(span, "`OverflowError` has been reported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Overflow(_) => {
|
Overflow(_) => {
|
||||||
bug!("overflow should be handled before the `report_selection_error` path");
|
bug!("overflow should be handled before the `report_selection_error` path");
|
||||||
}
|
}
|
||||||
|
@ -1471,6 +1470,12 @@ trait InferCtxtPrivExt<'tcx> {
|
||||||
terr: TypeError<'tcx>,
|
terr: TypeError<'tcx>,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
||||||
|
|
||||||
|
fn report_opaque_type_auto_trait_leakage(
|
||||||
|
&self,
|
||||||
|
obligation: &PredicateObligation<'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
||||||
|
|
||||||
fn report_type_parameter_mismatch_error(
|
fn report_type_parameter_mismatch_error(
|
||||||
&self,
|
&self,
|
||||||
obligation: &PredicateObligation<'tcx>,
|
obligation: &PredicateObligation<'tcx>,
|
||||||
|
@ -2646,11 +2651,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
if let ty::Param(ty::ParamTy { name, .. }) = *ty.kind() {
|
if let ty::Param(_) = *ty.kind() {
|
||||||
let infcx = self.infcx;
|
let infcx = self.infcx;
|
||||||
*self.var_map.entry(ty).or_insert_with(|| {
|
*self.var_map.entry(ty).or_insert_with(|| {
|
||||||
infcx.next_ty_var(TypeVariableOrigin {
|
infcx.next_ty_var(TypeVariableOrigin {
|
||||||
kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
|
kind: TypeVariableOriginKind::MiscVariable,
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -3192,6 +3197,39 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn report_opaque_type_auto_trait_leakage(
|
||||||
|
&self,
|
||||||
|
obligation: &PredicateObligation<'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
|
let name = match self.tcx.opaque_type_origin(def_id.expect_local()) {
|
||||||
|
hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => {
|
||||||
|
format!("opaque type")
|
||||||
|
}
|
||||||
|
hir::OpaqueTyOrigin::TyAlias { .. } => {
|
||||||
|
format!("`{}`", self.tcx.def_path_debug_str(def_id))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut err = self.tcx.sess.struct_span_err(
|
||||||
|
obligation.cause.span,
|
||||||
|
format!("cannot check whether the hidden type of {name} satisfies auto traits"),
|
||||||
|
);
|
||||||
|
err.span_note(self.tcx.def_span(def_id), "opaque type is declared here");
|
||||||
|
match self.defining_use_anchor {
|
||||||
|
DefiningAnchor::Bubble | DefiningAnchor::Error => {}
|
||||||
|
DefiningAnchor::Bind(bind) => {
|
||||||
|
err.span_note(
|
||||||
|
self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)),
|
||||||
|
"this item depends on auto traits of the hidden type, \
|
||||||
|
but may also be registering the hidden type. \
|
||||||
|
This is not supported right now. \
|
||||||
|
You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
err
|
||||||
|
}
|
||||||
|
|
||||||
fn report_type_parameter_mismatch_error(
|
fn report_type_parameter_mismatch_error(
|
||||||
&self,
|
&self,
|
||||||
obligation: &PredicateObligation<'tcx>,
|
obligation: &PredicateObligation<'tcx>,
|
||||||
|
|
|
@ -278,7 +278,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
// Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
|
// Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
|
||||||
if let ty::Array(aty, len) = self_ty.kind() {
|
if let ty::Array(aty, len) = self_ty.kind() {
|
||||||
flags.push((sym::_Self, Some("[]".to_string())));
|
flags.push((sym::_Self, Some("[]".to_string())));
|
||||||
let len = len.kind().try_to_value().and_then(|v| v.try_to_target_usize(self.tcx));
|
let len = len.try_to_value().and_then(|v| v.try_to_target_usize(self.tcx));
|
||||||
flags.push((sym::_Self, Some(format!("[{}; _]", aty))));
|
flags.push((sym::_Self, Some(format!("[{}; _]", aty))));
|
||||||
if let Some(n) = len {
|
if let Some(n) = len {
|
||||||
flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n))));
|
flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n))));
|
||||||
|
|
|
@ -528,7 +528,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||||
debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2);
|
debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2);
|
||||||
|
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use ty::ConstKind::Unevaluated;
|
use ty::Unevaluated;
|
||||||
match (c1.kind(), c2.kind()) {
|
match (c1.kind(), c2.kind()) {
|
||||||
(Unevaluated(a), Unevaluated(b))
|
(Unevaluated(a), Unevaluated(b))
|
||||||
if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
|
if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
|
||||||
|
|
|
@ -447,6 +447,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
|
||||||
depth: usize,
|
depth: usize,
|
||||||
obligations: &'a mut Vec<PredicateObligation<'tcx>>,
|
obligations: &'a mut Vec<PredicateObligation<'tcx>>,
|
||||||
) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
|
) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
|
||||||
|
debug_assert!(!selcx.infcx.next_trait_solver());
|
||||||
AssocTypeNormalizer {
|
AssocTypeNormalizer {
|
||||||
selcx,
|
selcx,
|
||||||
param_env,
|
param_env,
|
||||||
|
@ -1122,6 +1123,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
||||||
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
||||||
) -> Result<Option<Term<'tcx>>, InProgress> {
|
) -> Result<Option<Term<'tcx>>, InProgress> {
|
||||||
let infcx = selcx.infcx;
|
let infcx = selcx.infcx;
|
||||||
|
debug_assert!(!selcx.infcx.next_trait_solver());
|
||||||
// Don't use the projection cache in intercrate mode -
|
// Don't use the projection cache in intercrate mode -
|
||||||
// the `infcx` may be re-used between intercrate in non-intercrate
|
// the `infcx` may be re-used between intercrate in non-intercrate
|
||||||
// mode, which could lead to using incorrect cache results.
|
// mode, which could lead to using incorrect cache results.
|
||||||
|
|
|
@ -97,6 +97,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
assert!(!self.intercrate);
|
||||||
let c_pred = self.canonicalize_query_keep_static(
|
let c_pred = self.canonicalize_query_keep_static(
|
||||||
param_env.and(obligation.predicate),
|
param_env.and(obligation.predicate),
|
||||||
&mut _orig_values,
|
&mut _orig_values,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::solve;
|
||||||
use crate::traits::query::NoSolution;
|
use crate::traits::query::NoSolution;
|
||||||
use crate::traits::wf;
|
use crate::traits::wf;
|
||||||
use crate::traits::ObligationCtxt;
|
use crate::traits::ObligationCtxt;
|
||||||
|
@ -6,6 +7,7 @@ use rustc_infer::infer::canonical::Canonical;
|
||||||
use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
|
use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
|
||||||
use rustc_infer::traits::query::OutlivesBound;
|
use rustc_infer::traits::query::OutlivesBound;
|
||||||
use rustc_middle::infer::canonical::CanonicalQueryResponse;
|
use rustc_middle::infer::canonical::CanonicalQueryResponse;
|
||||||
|
use rustc_middle::traits::ObligationCause;
|
||||||
use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
|
use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_span::def_id::CRATE_DEF_ID;
|
use rustc_span::def_id::CRATE_DEF_ID;
|
||||||
use rustc_span::source_map::DUMMY_SP;
|
use rustc_span::source_map::DUMMY_SP;
|
||||||
|
@ -164,19 +166,29 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
|
||||||
|
|
||||||
// We lazily compute the outlives components as
|
// We lazily compute the outlives components as
|
||||||
// `select_all_or_error` constrains inference variables.
|
// `select_all_or_error` constrains inference variables.
|
||||||
let implied_bounds = outlives_bounds
|
let mut implied_bounds = Vec::new();
|
||||||
.into_iter()
|
for ty::OutlivesPredicate(a, r_b) in outlives_bounds {
|
||||||
.flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() {
|
match a.unpack() {
|
||||||
ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)],
|
ty::GenericArgKind::Lifetime(r_a) => {
|
||||||
|
implied_bounds.push(OutlivesBound::RegionSubRegion(r_b, r_a))
|
||||||
|
}
|
||||||
ty::GenericArgKind::Type(ty_a) => {
|
ty::GenericArgKind::Type(ty_a) => {
|
||||||
let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
|
let mut ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
|
||||||
|
// Need to manually normalize in the new solver as `wf::obligations` does not.
|
||||||
|
if ocx.infcx.next_trait_solver() {
|
||||||
|
ty_a = solve::deeply_normalize(
|
||||||
|
ocx.infcx.at(&ObligationCause::dummy(), param_env),
|
||||||
|
ty_a,
|
||||||
|
)
|
||||||
|
.map_err(|_errs| NoSolution)?;
|
||||||
|
}
|
||||||
let mut components = smallvec![];
|
let mut components = smallvec![];
|
||||||
push_outlives_components(tcx, ty_a, &mut components);
|
push_outlives_components(tcx, ty_a, &mut components);
|
||||||
implied_bounds_from_components(r_b, components)
|
implied_bounds.extend(implied_bounds_from_components(r_b, components))
|
||||||
}
|
}
|
||||||
ty::GenericArgKind::Const(_) => unreachable!(),
|
ty::GenericArgKind::Const(_) => unreachable!(),
|
||||||
})
|
}
|
||||||
.collect();
|
}
|
||||||
|
|
||||||
Ok(implied_bounds)
|
Ok(implied_bounds)
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,7 +388,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
/// `FnPtr`, when we wanted to report that it doesn't implement `Trait`.
|
/// `FnPtr`, when we wanted to report that it doesn't implement `Trait`.
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
fn reject_fn_ptr_impls(
|
fn reject_fn_ptr_impls(
|
||||||
&self,
|
&mut self,
|
||||||
impl_def_id: DefId,
|
impl_def_id: DefId,
|
||||||
obligation: &TraitObligation<'tcx>,
|
obligation: &TraitObligation<'tcx>,
|
||||||
impl_self_ty: Ty<'tcx>,
|
impl_self_ty: Ty<'tcx>,
|
||||||
|
@ -464,7 +464,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
|
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
if let Ok(r) = self.infcx.evaluate_obligation(&obligation) {
|
if let Ok(r) = self.evaluate_root_obligation(&obligation) {
|
||||||
if !r.may_apply() {
|
if !r.may_apply() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoImplCandidate => {
|
AutoImplCandidate => {
|
||||||
let data = self.confirm_auto_impl_candidate(obligation);
|
let data = self.confirm_auto_impl_candidate(obligation)?;
|
||||||
ImplSource::Builtin(data)
|
ImplSource::Builtin(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,12 +376,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
fn confirm_auto_impl_candidate(
|
fn confirm_auto_impl_candidate(
|
||||||
&mut self,
|
&mut self,
|
||||||
obligation: &TraitObligation<'tcx>,
|
obligation: &TraitObligation<'tcx>,
|
||||||
) -> Vec<PredicateObligation<'tcx>> {
|
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
|
||||||
debug!(?obligation, "confirm_auto_impl_candidate");
|
debug!(?obligation, "confirm_auto_impl_candidate");
|
||||||
|
|
||||||
let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
|
let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
|
||||||
let types = self.constituent_types_for_ty(self_ty);
|
let types = self.constituent_types_for_ty(self_ty)?;
|
||||||
self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types)
|
Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See `confirm_auto_impl_candidate`.
|
/// See `confirm_auto_impl_candidate`.
|
||||||
|
|
|
@ -34,8 +34,6 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::DefineOpaqueTypes;
|
use rustc_infer::infer::DefineOpaqueTypes;
|
||||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||||
use rustc_infer::traits::TraitEngine;
|
|
||||||
use rustc_infer::traits::TraitEngineExt;
|
|
||||||
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
|
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||||
|
@ -312,6 +310,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
stack: &TraitObligationStack<'o, 'tcx>,
|
stack: &TraitObligationStack<'o, 'tcx>,
|
||||||
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
|
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
|
||||||
|
debug_assert!(!self.infcx.next_trait_solver());
|
||||||
// Watch out for overflow. This intentionally bypasses (and does
|
// Watch out for overflow. This intentionally bypasses (and does
|
||||||
// not update) the cache.
|
// not update) the cache.
|
||||||
self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
|
self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
|
||||||
|
@ -526,21 +525,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
/// Evaluates whether the obligation `obligation` can be satisfied
|
/// Evaluates whether the obligation `obligation` can be satisfied
|
||||||
/// and returns an `EvaluationResult`. This is meant for the
|
/// and returns an `EvaluationResult`. This is meant for the
|
||||||
/// *initial* call.
|
/// *initial* call.
|
||||||
|
///
|
||||||
|
/// Do not use this directly, use `infcx.evaluate_obligation` instead.
|
||||||
pub fn evaluate_root_obligation(
|
pub fn evaluate_root_obligation(
|
||||||
&mut self,
|
&mut self,
|
||||||
obligation: &PredicateObligation<'tcx>,
|
obligation: &PredicateObligation<'tcx>,
|
||||||
) -> Result<EvaluationResult, OverflowError> {
|
) -> Result<EvaluationResult, OverflowError> {
|
||||||
|
debug_assert!(!self.infcx.next_trait_solver());
|
||||||
self.evaluation_probe(|this| {
|
self.evaluation_probe(|this| {
|
||||||
let goal =
|
let goal =
|
||||||
this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
|
this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
|
||||||
let mut result = if this.infcx.next_trait_solver() {
|
let mut result = this.evaluate_predicate_recursively(
|
||||||
this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])?
|
|
||||||
} else {
|
|
||||||
this.evaluate_predicate_recursively(
|
|
||||||
TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
|
TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
|
||||||
obligation.clone(),
|
obligation.clone(),
|
||||||
)?
|
)?;
|
||||||
};
|
|
||||||
// If the predicate has done any inference, then downgrade the
|
// If the predicate has done any inference, then downgrade the
|
||||||
// result to ambiguous.
|
// result to ambiguous.
|
||||||
if this.infcx.shallow_resolve(goal) != goal {
|
if this.infcx.shallow_resolve(goal) != goal {
|
||||||
|
@ -587,9 +585,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
|
I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
|
||||||
{
|
{
|
||||||
if self.infcx.next_trait_solver() {
|
|
||||||
self.evaluate_predicates_recursively_in_new_solver(predicates)
|
|
||||||
} else {
|
|
||||||
let mut result = EvaluatedToOk;
|
let mut result = EvaluatedToOk;
|
||||||
for mut obligation in predicates {
|
for mut obligation in predicates {
|
||||||
obligation.set_depth_from_parent(stack.depth());
|
obligation.set_depth_from_parent(stack.depth());
|
||||||
|
@ -604,26 +599,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Evaluates the predicates using the new solver when `-Ztrait-solver=next` is enabled
|
|
||||||
fn evaluate_predicates_recursively_in_new_solver(
|
|
||||||
&mut self,
|
|
||||||
predicates: impl IntoIterator<Item = PredicateObligation<'tcx>>,
|
|
||||||
) -> Result<EvaluationResult, OverflowError> {
|
|
||||||
let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(self.infcx);
|
|
||||||
fulfill_cx.register_predicate_obligations(self.infcx, predicates);
|
|
||||||
// True errors
|
|
||||||
// FIXME(-Ztrait-solver=next): Overflows are reported as ambig here, is that OK?
|
|
||||||
if !fulfill_cx.select_where_possible(self.infcx).is_empty() {
|
|
||||||
return Ok(EvaluatedToErr);
|
|
||||||
}
|
|
||||||
if !fulfill_cx.select_all_or_error(self.infcx).is_empty() {
|
|
||||||
return Ok(EvaluatedToAmbig);
|
|
||||||
}
|
|
||||||
// Regions and opaques are handled in the `evaluation_probe` by looking at the snapshot
|
|
||||||
Ok(EvaluatedToOk)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(
|
#[instrument(
|
||||||
level = "debug",
|
level = "debug",
|
||||||
|
@ -636,6 +611,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
previous_stack: TraitObligationStackList<'o, 'tcx>,
|
previous_stack: TraitObligationStackList<'o, 'tcx>,
|
||||||
obligation: PredicateObligation<'tcx>,
|
obligation: PredicateObligation<'tcx>,
|
||||||
) -> Result<EvaluationResult, OverflowError> {
|
) -> Result<EvaluationResult, OverflowError> {
|
||||||
|
debug_assert!(!self.infcx.next_trait_solver());
|
||||||
// `previous_stack` stores a `TraitObligation`, while `obligation` is
|
// `previous_stack` stores a `TraitObligation`, while `obligation` is
|
||||||
// a `PredicateObligation`. These are distinct types, so we can't
|
// a `PredicateObligation`. These are distinct types, so we can't
|
||||||
// use any `Option` combinator method that would force them to be
|
// use any `Option` combinator method that would force them to be
|
||||||
|
@ -897,7 +873,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
);
|
);
|
||||||
|
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use ty::ConstKind::Unevaluated;
|
use ty::Unevaluated;
|
||||||
match (c1.kind(), c2.kind()) {
|
match (c1.kind(), c2.kind()) {
|
||||||
(Unevaluated(a), Unevaluated(b))
|
(Unevaluated(a), Unevaluated(b))
|
||||||
if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
|
if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
|
||||||
|
@ -1179,6 +1155,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
stack: &TraitObligationStack<'o, 'tcx>,
|
stack: &TraitObligationStack<'o, 'tcx>,
|
||||||
) -> Result<EvaluationResult, OverflowError> {
|
) -> Result<EvaluationResult, OverflowError> {
|
||||||
|
debug_assert!(!self.infcx.next_trait_solver());
|
||||||
// In intercrate mode, whenever any of the generics are unbound,
|
// In intercrate mode, whenever any of the generics are unbound,
|
||||||
// there can always be an impl. Even if there are no impls in
|
// there can always be an impl. Even if there are no impls in
|
||||||
// this crate, perhaps the type would be unified with
|
// this crate, perhaps the type would be unified with
|
||||||
|
@ -2294,8 +2271,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||||
fn constituent_types_for_ty(
|
fn constituent_types_for_ty(
|
||||||
&self,
|
&self,
|
||||||
t: ty::Binder<'tcx, Ty<'tcx>>,
|
t: ty::Binder<'tcx, Ty<'tcx>>,
|
||||||
) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
|
) -> Result<ty::Binder<'tcx, Vec<Ty<'tcx>>>, SelectionError<'tcx>> {
|
||||||
match *t.skip_binder().kind() {
|
Ok(match *t.skip_binder().kind() {
|
||||||
ty::Uint(_)
|
ty::Uint(_)
|
||||||
| ty::Int(_)
|
| ty::Int(_)
|
||||||
| ty::Bool
|
| ty::Bool
|
||||||
|
@ -2359,12 +2336,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||||
|
let ty = self.tcx().type_of(def_id);
|
||||||
|
if ty.skip_binder().references_error() {
|
||||||
|
return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
|
||||||
|
}
|
||||||
// We can resolve the `impl Trait` to its concrete type,
|
// We can resolve the `impl Trait` to its concrete type,
|
||||||
// which enforces a DAG between the functions requiring
|
// which enforces a DAG between the functions requiring
|
||||||
// the auto trait bounds in question.
|
// the auto trait bounds in question.
|
||||||
t.rebind(vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)])
|
t.rebind(vec![ty.subst(self.tcx(), substs)])
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_predicates_for_types(
|
fn collect_predicates_for_types(
|
||||||
|
|
|
@ -302,6 +302,16 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec<traits::PredicateObligation<'tcx>> {
|
fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||||
|
// Do not normalize `wf` obligations with the new solver.
|
||||||
|
//
|
||||||
|
// The current deep normalization routine with the new solver does not
|
||||||
|
// handle ambiguity and the new solver correctly deals with unnnormalized goals.
|
||||||
|
// If the user relies on normalized types, e.g. for `fn implied_outlives_bounds`,
|
||||||
|
// it is their responsibility to normalize while avoiding ambiguity.
|
||||||
|
if infcx.next_trait_solver() {
|
||||||
|
return self.out;
|
||||||
|
}
|
||||||
|
|
||||||
let cause = self.cause(traits::WellFormed(None));
|
let cause = self.cause(traits::WellFormed(None));
|
||||||
let param_env = self.param_env;
|
let param_env = self.param_env;
|
||||||
let mut obligations = Vec::with_capacity(self.out.len());
|
let mut obligations = Vec::with_capacity(self.out.len());
|
||||||
|
|
|
@ -57,11 +57,19 @@ pub trait Interner: Sized {
|
||||||
type ParamTy: Clone + Debug + Hash + Ord;
|
type ParamTy: Clone + Debug + Hash + Ord;
|
||||||
type BoundTy: Clone + Debug + Hash + Ord;
|
type BoundTy: Clone + Debug + Hash + Ord;
|
||||||
type PlaceholderType: Clone + Debug + Hash + Ord;
|
type PlaceholderType: Clone + Debug + Hash + Ord;
|
||||||
type InferTy: Clone + Debug + Hash + Ord;
|
|
||||||
type ErrorGuaranteed: Clone + Debug + Hash + Ord;
|
type ErrorGuaranteed: Clone + Debug + Hash + Ord;
|
||||||
type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
|
type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
|
||||||
type AllocId: Clone + Debug + Hash + Ord;
|
type AllocId: Clone + Debug + Hash + Ord;
|
||||||
|
|
||||||
|
type InferConst: Clone + Debug + Hash + Ord;
|
||||||
|
type AliasConst: Clone + Debug + Hash + Ord;
|
||||||
|
type PlaceholderConst: Clone + Debug + Hash + Ord;
|
||||||
|
type ParamConst: Clone + Debug + Hash + Ord;
|
||||||
|
type BoundConst: Clone + Debug + Hash + Ord;
|
||||||
|
type InferTy: Clone + Debug + Hash + Ord;
|
||||||
|
type ValueConst: Clone + Debug + Hash + Ord;
|
||||||
|
type ExprConst: Clone + Debug + Hash + Ord;
|
||||||
|
|
||||||
type EarlyBoundRegion: Clone + Debug + Hash + Ord;
|
type EarlyBoundRegion: Clone + Debug + Hash + Ord;
|
||||||
type BoundRegion: Clone + Debug + Hash + Ord;
|
type BoundRegion: Clone + Debug + Hash + Ord;
|
||||||
type FreeRegion: Clone + Debug + Hash + Ord;
|
type FreeRegion: Clone + Debug + Hash + Ord;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||||
use crate::{FloatTy, IntTy, Interner, UintTy};
|
use crate::{ConstKind, FloatTy, IntTy, Interner, UintTy};
|
||||||
use rustc_data_structures::functor::IdFunctor;
|
use rustc_data_structures::functor::IdFunctor;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_index::{Idx, IndexVec};
|
use rustc_index::{Idx, IndexVec};
|
||||||
|
@ -182,3 +182,21 @@ impl fmt::Debug for FloatTy {
|
||||||
write!(f, "{}", self.name_str())
|
write!(f, "{}", self.name_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> fmt::Debug for ConstKind<I> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
use ConstKind::*;
|
||||||
|
match self {
|
||||||
|
Param(param) => write!(f, "{param:?}"),
|
||||||
|
Infer(var) => write!(f, "{var:?}"),
|
||||||
|
Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()),
|
||||||
|
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
|
||||||
|
Unevaluated(uv) => {
|
||||||
|
write!(f, "{uv:?}")
|
||||||
|
}
|
||||||
|
Value(valtree) => write!(f, "{valtree:?}"),
|
||||||
|
Error(_) => write!(f, "{{const error}}"),
|
||||||
|
Expr(expr) => write!(f, "{expr:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -876,6 +876,224 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents a constant in Rust.
|
||||||
|
// #[derive(derive_more::From)]
|
||||||
|
pub enum ConstKind<I: Interner> {
|
||||||
|
/// A const generic parameter.
|
||||||
|
Param(I::ParamConst),
|
||||||
|
|
||||||
|
/// Infer the value of the const.
|
||||||
|
Infer(I::InferConst),
|
||||||
|
|
||||||
|
/// Bound const variable, used only when preparing a trait query.
|
||||||
|
Bound(DebruijnIndex, I::BoundConst),
|
||||||
|
|
||||||
|
/// A placeholder const - universally quantified higher-ranked const.
|
||||||
|
Placeholder(I::PlaceholderConst),
|
||||||
|
|
||||||
|
/// An unnormalized const item such as an anon const or assoc const or free const item.
|
||||||
|
/// Right now anything other than anon consts does not actually work properly but this
|
||||||
|
/// should
|
||||||
|
Unevaluated(I::AliasConst),
|
||||||
|
|
||||||
|
/// Used to hold computed value.
|
||||||
|
Value(I::ValueConst),
|
||||||
|
|
||||||
|
/// A placeholder for a const which could not be computed; this is
|
||||||
|
/// propagated to avoid useless error messages.
|
||||||
|
Error(I::ErrorGuaranteed),
|
||||||
|
|
||||||
|
/// Unevaluated non-const-item, used by `feature(generic_const_exprs)` to represent
|
||||||
|
/// const arguments such as `N + 1` or `foo(N)`
|
||||||
|
Expr(I::ExprConst),
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
|
||||||
|
match value {
|
||||||
|
ConstKind::Param(_) => 0,
|
||||||
|
ConstKind::Infer(_) => 1,
|
||||||
|
ConstKind::Bound(_, _) => 2,
|
||||||
|
ConstKind::Placeholder(_) => 3,
|
||||||
|
ConstKind::Unevaluated(_) => 4,
|
||||||
|
ConstKind::Value(_) => 5,
|
||||||
|
ConstKind::Error(_) => 6,
|
||||||
|
ConstKind::Expr(_) => 7,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> hash::Hash for ConstKind<I> {
|
||||||
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
|
const_kind_discriminant(self).hash(state);
|
||||||
|
match self {
|
||||||
|
ConstKind::Param(p) => p.hash(state),
|
||||||
|
ConstKind::Infer(i) => i.hash(state),
|
||||||
|
ConstKind::Bound(d, b) => {
|
||||||
|
d.hash(state);
|
||||||
|
b.hash(state);
|
||||||
|
}
|
||||||
|
ConstKind::Placeholder(p) => p.hash(state),
|
||||||
|
ConstKind::Unevaluated(u) => u.hash(state),
|
||||||
|
ConstKind::Value(v) => v.hash(state),
|
||||||
|
ConstKind::Error(e) => e.hash(state),
|
||||||
|
ConstKind::Expr(e) => e.hash(state),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
|
||||||
|
where
|
||||||
|
I::ParamConst: HashStable<CTX>,
|
||||||
|
I::InferConst: HashStable<CTX>,
|
||||||
|
I::BoundConst: HashStable<CTX>,
|
||||||
|
I::PlaceholderConst: HashStable<CTX>,
|
||||||
|
I::AliasConst: HashStable<CTX>,
|
||||||
|
I::ValueConst: HashStable<CTX>,
|
||||||
|
I::ErrorGuaranteed: HashStable<CTX>,
|
||||||
|
I::ExprConst: HashStable<CTX>,
|
||||||
|
{
|
||||||
|
fn hash_stable(
|
||||||
|
&self,
|
||||||
|
hcx: &mut CTX,
|
||||||
|
hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
|
||||||
|
) {
|
||||||
|
const_kind_discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
match self {
|
||||||
|
ConstKind::Param(p) => p.hash_stable(hcx, hasher),
|
||||||
|
ConstKind::Infer(i) => i.hash_stable(hcx, hasher),
|
||||||
|
ConstKind::Bound(d, b) => {
|
||||||
|
d.hash_stable(hcx, hasher);
|
||||||
|
b.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
ConstKind::Placeholder(p) => p.hash_stable(hcx, hasher),
|
||||||
|
ConstKind::Unevaluated(u) => u.hash_stable(hcx, hasher),
|
||||||
|
ConstKind::Value(v) => v.hash_stable(hcx, hasher),
|
||||||
|
ConstKind::Error(e) => e.hash_stable(hcx, hasher),
|
||||||
|
ConstKind::Expr(e) => e.hash_stable(hcx, hasher),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ConstKind<I>
|
||||||
|
where
|
||||||
|
I::ParamConst: Decodable<D>,
|
||||||
|
I::InferConst: Decodable<D>,
|
||||||
|
I::BoundConst: Decodable<D>,
|
||||||
|
I::PlaceholderConst: Decodable<D>,
|
||||||
|
I::AliasConst: Decodable<D>,
|
||||||
|
I::ValueConst: Decodable<D>,
|
||||||
|
I::ErrorGuaranteed: Decodable<D>,
|
||||||
|
I::ExprConst: Decodable<D>,
|
||||||
|
{
|
||||||
|
fn decode(d: &mut D) -> Self {
|
||||||
|
match Decoder::read_usize(d) {
|
||||||
|
0 => ConstKind::Param(Decodable::decode(d)),
|
||||||
|
1 => ConstKind::Infer(Decodable::decode(d)),
|
||||||
|
2 => ConstKind::Bound(Decodable::decode(d), Decodable::decode(d)),
|
||||||
|
3 => ConstKind::Placeholder(Decodable::decode(d)),
|
||||||
|
4 => ConstKind::Unevaluated(Decodable::decode(d)),
|
||||||
|
5 => ConstKind::Value(Decodable::decode(d)),
|
||||||
|
6 => ConstKind::Error(Decodable::decode(d)),
|
||||||
|
7 => ConstKind::Expr(Decodable::decode(d)),
|
||||||
|
_ => panic!(
|
||||||
|
"{}",
|
||||||
|
format!(
|
||||||
|
"invalid enum variant tag while decoding `{}`, expected 0..{}",
|
||||||
|
"ConstKind", 8,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for ConstKind<I>
|
||||||
|
where
|
||||||
|
I::ParamConst: Encodable<E>,
|
||||||
|
I::InferConst: Encodable<E>,
|
||||||
|
I::BoundConst: Encodable<E>,
|
||||||
|
I::PlaceholderConst: Encodable<E>,
|
||||||
|
I::AliasConst: Encodable<E>,
|
||||||
|
I::ValueConst: Encodable<E>,
|
||||||
|
I::ErrorGuaranteed: Encodable<E>,
|
||||||
|
I::ExprConst: Encodable<E>,
|
||||||
|
{
|
||||||
|
fn encode(&self, e: &mut E) {
|
||||||
|
let disc = const_kind_discriminant(self);
|
||||||
|
match self {
|
||||||
|
ConstKind::Param(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
|
||||||
|
ConstKind::Infer(i) => e.emit_enum_variant(disc, |e| i.encode(e)),
|
||||||
|
ConstKind::Bound(d, b) => e.emit_enum_variant(disc, |e| {
|
||||||
|
d.encode(e);
|
||||||
|
b.encode(e);
|
||||||
|
}),
|
||||||
|
ConstKind::Placeholder(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
|
||||||
|
ConstKind::Unevaluated(u) => e.emit_enum_variant(disc, |e| u.encode(e)),
|
||||||
|
ConstKind::Value(v) => e.emit_enum_variant(disc, |e| v.encode(e)),
|
||||||
|
ConstKind::Error(er) => e.emit_enum_variant(disc, |e| er.encode(e)),
|
||||||
|
ConstKind::Expr(ex) => e.emit_enum_variant(disc, |e| ex.encode(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> PartialOrd for ConstKind<I> {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> Ord for ConstKind<I> {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
const_kind_discriminant(self)
|
||||||
|
.cmp(&const_kind_discriminant(other))
|
||||||
|
.then_with(|| match (self, other) {
|
||||||
|
(ConstKind::Param(p1), ConstKind::Param(p2)) => p1.cmp(p2),
|
||||||
|
(ConstKind::Infer(i1), ConstKind::Infer(i2)) => i1.cmp(i2),
|
||||||
|
(ConstKind::Bound(d1, b1), ConstKind::Bound(d2, b2)) => d1.cmp(d2).then_with(|| b1.cmp(b2)),
|
||||||
|
(ConstKind::Placeholder(p1), ConstKind::Placeholder(p2)) => p1.cmp(p2),
|
||||||
|
(ConstKind::Unevaluated(u1), ConstKind::Unevaluated(u2)) => u1.cmp(u2),
|
||||||
|
(ConstKind::Value(v1), ConstKind::Value(v2)) => v1.cmp(v2),
|
||||||
|
(ConstKind::Error(e1), ConstKind::Error(e2)) => e1.cmp(e2),
|
||||||
|
(ConstKind::Expr(e1), ConstKind::Expr(e2)) => e1.cmp(e2),
|
||||||
|
_ => {
|
||||||
|
debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}");
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> PartialEq for ConstKind<I> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
match (self, other) {
|
||||||
|
(Self::Param(l0), Self::Param(r0)) => l0 == r0,
|
||||||
|
(Self::Infer(l0), Self::Infer(r0)) => l0 == r0,
|
||||||
|
(Self::Bound(l0, l1), Self::Bound(r0, r1)) => l0 == r0 && l1 == r1,
|
||||||
|
(Self::Placeholder(l0), Self::Placeholder(r0)) => l0 == r0,
|
||||||
|
(Self::Unevaluated(l0), Self::Unevaluated(r0)) => l0 == r0,
|
||||||
|
(Self::Value(l0), Self::Value(r0)) => l0 == r0,
|
||||||
|
(Self::Error(l0), Self::Error(r0)) => l0 == r0,
|
||||||
|
(Self::Expr(l0), Self::Expr(r0)) => l0 == r0,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> Eq for ConstKind<I> {}
|
||||||
|
|
||||||
|
impl<I: Interner> Clone for ConstKind<I> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::Param(arg0) => Self::Param(arg0.clone()),
|
||||||
|
Self::Infer(arg0) => Self::Infer(arg0.clone()),
|
||||||
|
Self::Bound(arg0, arg1) => Self::Bound(arg0.clone(), arg1.clone()),
|
||||||
|
Self::Placeholder(arg0) => Self::Placeholder(arg0.clone()),
|
||||||
|
Self::Unevaluated(arg0) => Self::Unevaluated(arg0.clone()),
|
||||||
|
Self::Value(arg0) => Self::Value(arg0.clone()),
|
||||||
|
Self::Error(arg0) => Self::Error(arg0.clone()),
|
||||||
|
Self::Expr(arg0) => Self::Expr(arg0.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Representation of regions. Note that the NLL checker uses a distinct
|
/// Representation of regions. Note that the NLL checker uses a distinct
|
||||||
/// representation of regions. For this reason, it internally replaces all the
|
/// representation of regions. For this reason, it internally replaces all the
|
||||||
/// regions with inference variables -- the index of the variable is then used
|
/// regions with inference variables -- the index of the variable is then used
|
||||||
|
|
|
@ -132,7 +132,12 @@ mod c_char_definition {
|
||||||
),
|
),
|
||||||
all(
|
all(
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
|
any(
|
||||||
|
target_arch = "aarch64",
|
||||||
|
target_arch = "arm",
|
||||||
|
target_arch = "powerpc",
|
||||||
|
target_arch = "riscv64"
|
||||||
|
)
|
||||||
),
|
),
|
||||||
all(
|
all(
|
||||||
target_os = "vxworks",
|
target_os = "vxworks",
|
||||||
|
|
|
@ -16,6 +16,8 @@ ignore = [
|
||||||
"tests",
|
"tests",
|
||||||
|
|
||||||
# do not format submodules
|
# do not format submodules
|
||||||
|
# FIXME: sync submodule list with tidy/bootstrap/etc
|
||||||
|
# tidy/src/walk.rs:filter_dirs
|
||||||
"library/backtrace",
|
"library/backtrace",
|
||||||
"library/portable-simd",
|
"library/portable-simd",
|
||||||
"library/stdarch",
|
"library/stdarch",
|
||||||
|
@ -31,10 +33,8 @@ ignore = [
|
||||||
"src/tools/cargo",
|
"src/tools/cargo",
|
||||||
"src/tools/clippy",
|
"src/tools/clippy",
|
||||||
"src/tools/miri",
|
"src/tools/miri",
|
||||||
"src/tools/rls",
|
|
||||||
"src/tools/rust-analyzer",
|
"src/tools/rust-analyzer",
|
||||||
"src/tools/rustfmt",
|
"src/tools/rustfmt",
|
||||||
"src/tools/rust-installer",
|
|
||||||
|
|
||||||
# these are ignored by a standard cargo fmt run
|
# these are ignored by a standard cargo fmt run
|
||||||
"compiler/rustc_codegen_cranelift/y.rs", # running rustfmt breaks this file
|
"compiler/rustc_codegen_cranelift/y.rs", # running rustfmt breaks this file
|
||||||
|
|
|
@ -380,7 +380,10 @@ impl Step for Llvm {
|
||||||
cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
|
cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
|
||||||
}
|
}
|
||||||
|
|
||||||
if target.starts_with("riscv") && !target.contains("freebsd") && !target.contains("openbsd")
|
if target.starts_with("riscv")
|
||||||
|
&& !target.contains("freebsd")
|
||||||
|
&& !target.contains("openbsd")
|
||||||
|
&& !target.contains("netbsd")
|
||||||
{
|
{
|
||||||
// RISC-V GCC erroneously requires linking against
|
// RISC-V GCC erroneously requires linking against
|
||||||
// `libatomic` when using 1-byte and 2-byte C++
|
// `libatomic` when using 1-byte and 2-byte C++
|
||||||
|
|
|
@ -289,7 +289,7 @@ bootstrap_tool!(
|
||||||
Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = "test";
|
Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = "test";
|
||||||
BuildManifest, "src/tools/build-manifest", "build-manifest";
|
BuildManifest, "src/tools/build-manifest", "build-manifest";
|
||||||
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
|
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
|
||||||
RustInstaller, "src/tools/rust-installer", "rust-installer", is_external_tool = true;
|
RustInstaller, "src/tools/rust-installer", "rust-installer";
|
||||||
RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes";
|
RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes";
|
||||||
ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors";
|
ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors";
|
||||||
LintDocs, "src/tools/lint-docs", "lint-docs";
|
LintDocs, "src/tools/lint-docs", "lint-docs";
|
||||||
|
|
|
@ -305,6 +305,7 @@ target | std | host | notes
|
||||||
`riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD
|
`riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD
|
||||||
`riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia
|
`riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia
|
||||||
`riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0)
|
`riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0)
|
||||||
|
[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ? | RISC-V NetBSD
|
||||||
[`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
|
[`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
|
||||||
`s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL)
|
`s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL)
|
||||||
`sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux
|
`sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux
|
||||||
|
|
|
@ -22,6 +22,7 @@ are currently defined running NetBSD:
|
||||||
| `i686-unknown-netbsd` | [32-bit i386 with SSE](https://wiki.netbsd.org/ports/i386/) |
|
| `i686-unknown-netbsd` | [32-bit i386 with SSE](https://wiki.netbsd.org/ports/i386/) |
|
||||||
| `mipsel-unknown-netbsd` | [32-bit mips, requires mips32 cpu support](https://wiki.netbsd.org/ports/evbmips/) |
|
| `mipsel-unknown-netbsd` | [32-bit mips, requires mips32 cpu support](https://wiki.netbsd.org/ports/evbmips/) |
|
||||||
| `powerpc-unknown-netbsd` | [Various 32-bit PowerPC systems, e.g. MacPPC](https://wiki.netbsd.org/ports/macppc/) |
|
| `powerpc-unknown-netbsd` | [Various 32-bit PowerPC systems, e.g. MacPPC](https://wiki.netbsd.org/ports/macppc/) |
|
||||||
|
| `riscv64gc-unknown-netbsd` | [64-bit RISC-V](https://wiki.netbsd.org/ports/riscv/)
|
||||||
| `sparc64-unknown-netbsd` | [Sun UltraSPARC systems](https://wiki.netbsd.org/ports/sparc64/) |
|
| `sparc64-unknown-netbsd` | [Sun UltraSPARC systems](https://wiki.netbsd.org/ports/sparc64/) |
|
||||||
|
|
||||||
All use the "native" `stdc++` library which goes along with the natively
|
All use the "native" `stdc++` library which goes along with the natively
|
||||||
|
|
|
@ -689,7 +689,7 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t
|
||||||
mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
|
mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
|
||||||
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
|
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
|
||||||
ty::Array(sub_type, len) => match sub_type.kind() {
|
ty::Array(sub_type, len) => match sub_type.kind() {
|
||||||
ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(lcx.tcx) {
|
ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) {
|
||||||
Some(len) => alloc
|
Some(len) => alloc
|
||||||
.inner()
|
.inner()
|
||||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
|
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
|
||||||
|
@ -700,7 +700,7 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t
|
||||||
.map(Constant::Vec),
|
.map(Constant::Vec),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(lcx.tcx) {
|
ty::Float(FloatTy::F64) => match len.try_to_target_usize(lcx.tcx) {
|
||||||
Some(len) => alloc
|
Some(len) => alloc
|
||||||
.inner()
|
.inner()
|
||||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
|
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
|
||||||
|
|
|
@ -468,7 +468,8 @@ uninstall_components() {
|
||||||
verbose_msg "removing component manifest $_component_manifest"
|
verbose_msg "removing component manifest $_component_manifest"
|
||||||
run rm "$_component_manifest"
|
run rm "$_component_manifest"
|
||||||
# This is a hard error because the installation is unrecoverable
|
# This is a hard error because the installation is unrecoverable
|
||||||
critical_need_ok "failed to remove installed manifest for component '$_installed_component'"
|
local _err_cant_r_manifest="failed to remove installed manifest for component"
|
||||||
|
critical_need_ok "$_err_cant_r_manifest '$_installed_component'"
|
||||||
|
|
||||||
# Update the installed component list
|
# Update the installed component list
|
||||||
local _modified_components="$(sed "/^$_installed_component\$/d" "$_md/components")"
|
local _modified_components="$(sed "/^$_installed_component\$/d" "$_md/components")"
|
||||||
|
@ -692,7 +693,9 @@ maybe_configure_ld() {
|
||||||
fi
|
fi
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
warn "failed to run ldconfig. this may happen when not installing as root. run with --verbose to see the error"
|
local _warn_s="failed to run ldconfig. this may happen when \
|
||||||
|
not installing as root. run with --verbose to see the error"
|
||||||
|
warn "$_warn_s"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
@ -977,7 +980,9 @@ make_dir_recursive "$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR"
|
||||||
need_ok "failed to create $TEMPLATE_REL_MANIFEST_DIR"
|
need_ok "failed to create $TEMPLATE_REL_MANIFEST_DIR"
|
||||||
|
|
||||||
# Drop the version number into the manifest dir
|
# Drop the version number into the manifest dir
|
||||||
write_to_file "$TEMPLATE_RUST_INSTALLER_VERSION" "$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version"
|
write_to_file "$TEMPLATE_RUST_INSTALLER_VERSION" \
|
||||||
|
"$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version"
|
||||||
|
|
||||||
critical_need_ok "failed to write installer version"
|
critical_need_ok "failed to write installer version"
|
||||||
|
|
||||||
# Install the uninstaller
|
# Install the uninstaller
|
||||||
|
@ -992,5 +997,3 @@ maybe_configure_ld "$abs_libdir"
|
||||||
echo
|
echo
|
||||||
echo " $TEMPLATE_SUCCESS_MESSAGE"
|
echo " $TEMPLATE_SUCCESS_MESSAGE"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,25 +71,16 @@ impl Combiner {
|
||||||
|
|
||||||
// Merge each installer into the work directory of the new installer.
|
// Merge each installer into the work directory of the new installer.
|
||||||
let components = create_new_file(package_dir.join("components"))?;
|
let components = create_new_file(package_dir.join("components"))?;
|
||||||
for input_tarball in self
|
for input_tarball in self.input_tarballs.split(',').map(str::trim).filter(|s| !s.is_empty())
|
||||||
.input_tarballs
|
|
||||||
.split(',')
|
|
||||||
.map(str::trim)
|
|
||||||
.filter(|s| !s.is_empty())
|
|
||||||
{
|
{
|
||||||
// Extract the input tarballs
|
// Extract the input tarballs
|
||||||
let compression =
|
let compression =
|
||||||
CompressionFormat::detect_from_path(input_tarball).ok_or_else(|| {
|
CompressionFormat::detect_from_path(input_tarball).ok_or_else(|| {
|
||||||
anyhow::anyhow!("couldn't figure out the format of {}", input_tarball)
|
anyhow::anyhow!("couldn't figure out the format of {}", input_tarball)
|
||||||
})?;
|
})?;
|
||||||
Archive::new(compression.decode(input_tarball)?)
|
Archive::new(compression.decode(input_tarball)?).unpack(&self.work_dir).with_context(
|
||||||
.unpack(&self.work_dir)
|
|| format!("unable to extract '{}' into '{}'", &input_tarball, self.work_dir),
|
||||||
.with_context(|| {
|
)?;
|
||||||
format!(
|
|
||||||
"unable to extract '{}' into '{}'",
|
|
||||||
&input_tarball, self.work_dir
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let pkg_name =
|
let pkg_name =
|
||||||
input_tarball.trim_end_matches(&format!(".tar.{}", compression.extension()));
|
input_tarball.trim_end_matches(&format!(".tar.{}", compression.extension()));
|
||||||
|
@ -126,11 +117,7 @@ impl Combiner {
|
||||||
|
|
||||||
// Write the installer version.
|
// Write the installer version.
|
||||||
let version = package_dir.join("rust-installer-version");
|
let version = package_dir.join("rust-installer-version");
|
||||||
writeln!(
|
writeln!(create_new_file(version)?, "{}", crate::RUST_INSTALLER_VERSION)
|
||||||
create_new_file(version)?,
|
|
||||||
"{}",
|
|
||||||
crate::RUST_INSTALLER_VERSION
|
|
||||||
)
|
|
||||||
.context("failed to write new installer version")?;
|
.context("failed to write new installer version")?;
|
||||||
|
|
||||||
// Copy the overlay.
|
// Copy the overlay.
|
||||||
|
|
|
@ -86,11 +86,7 @@ impl Generator {
|
||||||
|
|
||||||
// Write the installer version (only used by combine-installers.sh)
|
// Write the installer version (only used by combine-installers.sh)
|
||||||
let version = package_dir.join("rust-installer-version");
|
let version = package_dir.join("rust-installer-version");
|
||||||
writeln!(
|
writeln!(create_new_file(version)?, "{}", crate::RUST_INSTALLER_VERSION)
|
||||||
create_new_file(version)?,
|
|
||||||
"{}",
|
|
||||||
crate::RUST_INSTALLER_VERSION
|
|
||||||
)
|
|
||||||
.context("failed to write new installer version")?;
|
.context("failed to write new installer version")?;
|
||||||
|
|
||||||
// Copy the overlay
|
// Copy the overlay
|
||||||
|
@ -128,33 +124,19 @@ impl Generator {
|
||||||
/// Copies the `src` directory recursively to `dst`, writing `manifest.in` too.
|
/// Copies the `src` directory recursively to `dst`, writing `manifest.in` too.
|
||||||
fn copy_and_manifest(src: &Path, dst: &Path, bulk_dirs: &str) -> Result<()> {
|
fn copy_and_manifest(src: &Path, dst: &Path, bulk_dirs: &str) -> Result<()> {
|
||||||
let mut manifest = create_new_file(dst.join("manifest.in"))?;
|
let mut manifest = create_new_file(dst.join("manifest.in"))?;
|
||||||
let bulk_dirs: Vec<_> = bulk_dirs
|
let bulk_dirs: Vec<_> = bulk_dirs.split(',').filter(|s| !s.is_empty()).map(Path::new).collect();
|
||||||
.split(',')
|
|
||||||
.filter(|s| !s.is_empty())
|
|
||||||
.map(Path::new)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut paths = BTreeSet::new();
|
let mut paths = BTreeSet::new();
|
||||||
copy_with_callback(src, dst, |path, file_type| {
|
copy_with_callback(src, dst, |path, file_type| {
|
||||||
// We need paths to be compatible with both Unix and Windows.
|
// We need paths to be compatible with both Unix and Windows.
|
||||||
if path
|
if path.components().filter_map(|c| c.as_os_str().to_str()).any(|s| s.contains('\\')) {
|
||||||
.components()
|
bail!("rust-installer doesn't support '\\' in path components: {:?}", path);
|
||||||
.filter_map(|c| c.as_os_str().to_str())
|
|
||||||
.any(|s| s.contains('\\'))
|
|
||||||
{
|
|
||||||
bail!(
|
|
||||||
"rust-installer doesn't support '\\' in path components: {:?}",
|
|
||||||
path
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize to Unix-style path separators.
|
// Normalize to Unix-style path separators.
|
||||||
let normalized_string;
|
let normalized_string;
|
||||||
let mut string = path.to_str().ok_or_else(|| {
|
let mut string = path.to_str().ok_or_else(|| {
|
||||||
format_err!(
|
format_err!("rust-installer doesn't support non-Unicode paths: {:?}", path)
|
||||||
"rust-installer doesn't support non-Unicode paths: {:?}",
|
|
||||||
path
|
|
||||||
)
|
|
||||||
})?;
|
})?;
|
||||||
if string.contains('\\') {
|
if string.contains('\\') {
|
||||||
normalized_string = string.replace('\\', "/");
|
normalized_string = string.replace('\\', "/");
|
||||||
|
|
|
@ -19,8 +19,12 @@ fn main() -> Result<()> {
|
||||||
let command_line = CommandLine::parse();
|
let command_line = CommandLine::parse();
|
||||||
match command_line.command {
|
match command_line.command {
|
||||||
Subcommand::Combine(combiner) => combiner.run().context("failed to combine installers")?,
|
Subcommand::Combine(combiner) => combiner.run().context("failed to combine installers")?,
|
||||||
Subcommand::Generate(generator) => generator.run().context("failed to generate installer")?,
|
Subcommand::Generate(generator) => {
|
||||||
Subcommand::Script(scripter) => scripter.run().context("failed to generate installation script")?,
|
generator.run().context("failed to generate installer")?
|
||||||
|
}
|
||||||
|
Subcommand::Script(scripter) => {
|
||||||
|
scripter.run().context("failed to generate installation script")?
|
||||||
|
}
|
||||||
Subcommand::Tarball(tarballer) => tarballer.run().context("failed to generate tarballs")?,
|
Subcommand::Tarball(tarballer) => tarballer.run().context("failed to generate tarballs")?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -32,22 +32,19 @@ actor! {
|
||||||
impl Scripter {
|
impl Scripter {
|
||||||
/// Generates the actual installer script
|
/// Generates the actual installer script
|
||||||
pub fn run(self) -> Result<()> {
|
pub fn run(self) -> Result<()> {
|
||||||
// Replace dashes in the success message with spaces (our arg handling botches spaces)
|
// Replace dashes in the product name with spaces (our arg handling botches spaces)
|
||||||
// TODO: still needed? Kept for compatibility for now.
|
// FIXME: still needed? Kept for compatibility for now.
|
||||||
let product_name = self.product_name.replace('-', " ");
|
let product_name = self.product_name.replace('-', " ");
|
||||||
|
|
||||||
// Replace dashes in the success message with spaces (our arg handling botches spaces)
|
// Replace dashes in the success message with spaces (our arg handling botches spaces)
|
||||||
// TODO: still needed? Kept for compatibility for now.
|
// FIXME: still needed? Kept for compatibility for now.
|
||||||
let success_message = self.success_message.replace('-', " ");
|
let success_message = self.success_message.replace('-', " ");
|
||||||
|
|
||||||
let script = TEMPLATE
|
let script = TEMPLATE
|
||||||
.replace("%%TEMPLATE_PRODUCT_NAME%%", &sh_quote(&product_name))
|
.replace("%%TEMPLATE_PRODUCT_NAME%%", &sh_quote(&product_name))
|
||||||
.replace("%%TEMPLATE_REL_MANIFEST_DIR%%", &self.rel_manifest_dir)
|
.replace("%%TEMPLATE_REL_MANIFEST_DIR%%", &self.rel_manifest_dir)
|
||||||
.replace("%%TEMPLATE_SUCCESS_MESSAGE%%", &sh_quote(&success_message))
|
.replace("%%TEMPLATE_SUCCESS_MESSAGE%%", &sh_quote(&success_message))
|
||||||
.replace(
|
.replace("%%TEMPLATE_LEGACY_MANIFEST_DIRS%%", &sh_quote(&self.legacy_manifest_dirs))
|
||||||
"%%TEMPLATE_LEGACY_MANIFEST_DIRS%%",
|
|
||||||
&sh_quote(&self.legacy_manifest_dirs),
|
|
||||||
)
|
|
||||||
.replace(
|
.replace(
|
||||||
"%%TEMPLATE_RUST_INSTALLER_VERSION%%",
|
"%%TEMPLATE_RUST_INSTALLER_VERSION%%",
|
||||||
&sh_quote(&crate::RUST_INSTALLER_VERSION),
|
&sh_quote(&crate::RUST_INSTALLER_VERSION),
|
||||||
|
|
|
@ -58,10 +58,7 @@ impl Tarballer {
|
||||||
let buf = BufWriter::with_capacity(1024 * 1024, encoder);
|
let buf = BufWriter::with_capacity(1024 * 1024, encoder);
|
||||||
let mut builder = Builder::new(buf);
|
let mut builder = Builder::new(buf);
|
||||||
|
|
||||||
let pool = rayon::ThreadPoolBuilder::new()
|
let pool = rayon::ThreadPoolBuilder::new().num_threads(2).build().unwrap();
|
||||||
.num_threads(2)
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
pool.install(move || {
|
pool.install(move || {
|
||||||
for path in dirs {
|
for path in dirs {
|
||||||
let src = Path::new(&self.work_dir).join(&path);
|
let src = Path::new(&self.work_dir).join(&path);
|
||||||
|
@ -122,11 +119,7 @@ where
|
||||||
let name = name.as_ref();
|
let name = name.as_ref();
|
||||||
|
|
||||||
if !name.is_relative() && !name.starts_with(root) {
|
if !name.is_relative() && !name.starts_with(root) {
|
||||||
bail!(
|
bail!("input '{}' is not in work dir '{}'", name.display(), root.display());
|
||||||
"input '{}' is not in work dir '{}'",
|
|
||||||
name.display(),
|
|
||||||
root.display()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut dirs = vec![];
|
let mut dirs = vec![];
|
||||||
|
|
|
@ -15,8 +15,7 @@ use std::os::windows::fs::symlink_file;
|
||||||
|
|
||||||
/// Converts a `&Path` to a UTF-8 `&str`.
|
/// Converts a `&Path` to a UTF-8 `&str`.
|
||||||
pub fn path_to_str(path: &Path) -> Result<&str> {
|
pub fn path_to_str(path: &Path) -> Result<&str> {
|
||||||
path.to_str()
|
path.to_str().ok_or_else(|| format_err!("path is not valid UTF-8 '{}'", path.display()))
|
||||||
.ok_or_else(|| format_err!("path is not valid UTF-8 '{}'", path.display()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps `fs::copy` with a nicer error message.
|
/// Wraps `fs::copy` with a nicer error message.
|
||||||
|
@ -27,11 +26,7 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<u64> {
|
||||||
Ok(0)
|
Ok(0)
|
||||||
} else {
|
} else {
|
||||||
let amt = fs::copy(&from, &to).with_context(|| {
|
let amt = fs::copy(&from, &to).with_context(|| {
|
||||||
format!(
|
format!("failed to copy '{}' to '{}'", from.as_ref().display(), to.as_ref().display())
|
||||||
"failed to copy '{}' to '{}'",
|
|
||||||
from.as_ref().display(),
|
|
||||||
to.as_ref().display()
|
|
||||||
)
|
|
||||||
})?;
|
})?;
|
||||||
Ok(amt)
|
Ok(amt)
|
||||||
}
|
}
|
||||||
|
@ -123,8 +118,12 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! actor_field_default {
|
macro_rules! actor_field_default {
|
||||||
() => { Default::default() };
|
() => {
|
||||||
(= $expr:expr) => { $expr.into() }
|
Default::default()
|
||||||
|
};
|
||||||
|
(= $expr:expr) => {
|
||||||
|
$expr.into()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an "actor" with default values, setters for all fields, and Clap parser support.
|
/// Creates an "actor" with default values, setters for all fields, and Clap parser support.
|
||||||
|
|
|
@ -458,7 +458,8 @@ uninstall_from_installed_script_with_args_fails() {
|
||||||
--output-dir="$OUT_DIR/c1" \
|
--output-dir="$OUT_DIR/c1" \
|
||||||
--component-name=rustc
|
--component-name=rustc
|
||||||
try "$WORK_DIR/c1/package/install.sh" --prefix="$PREFIX_DIR"
|
try "$WORK_DIR/c1/package/install.sh" --prefix="$PREFIX_DIR"
|
||||||
expect_output_fail "uninstall.sh does not take any arguments" sh "$PREFIX_DIR/lib/packagelib/uninstall.sh" --prefix=foo
|
expect_output_fail "uninstall.sh does not take any arguments" \
|
||||||
|
sh "$PREFIX_DIR/lib/packagelib/uninstall.sh" --prefix=foo
|
||||||
}
|
}
|
||||||
runtest uninstall_from_installed_script_with_args_fails
|
runtest uninstall_from_installed_script_with_args_fails
|
||||||
|
|
||||||
|
@ -680,7 +681,8 @@ select_components_to_install() {
|
||||||
try test -e "$PREFIX_DIR/bin/program"
|
try test -e "$PREFIX_DIR/bin/program"
|
||||||
try test -e "$PREFIX_DIR/bin/cargo"
|
try test -e "$PREFIX_DIR/bin/cargo"
|
||||||
try test ! -e "$PREFIX_DIR/baz"
|
try test ! -e "$PREFIX_DIR/baz"
|
||||||
try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" --components=rustc,cargo,rust-docs
|
try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" \
|
||||||
|
--components=rustc,cargo,rust-docs
|
||||||
try test ! -e "$PREFIX_DIR/bin/program"
|
try test ! -e "$PREFIX_DIR/bin/program"
|
||||||
try test ! -e "$PREFIX_DIR/bin/cargo"
|
try test ! -e "$PREFIX_DIR/bin/cargo"
|
||||||
try test ! -e "$PREFIX_DIR/baz"
|
try test ! -e "$PREFIX_DIR/baz"
|
||||||
|
@ -733,7 +735,8 @@ select_components_to_uninstall() {
|
||||||
try test ! -e "$PREFIX_DIR/bin/cargo"
|
try test ! -e "$PREFIX_DIR/bin/cargo"
|
||||||
try test -e "$PREFIX_DIR/baz"
|
try test -e "$PREFIX_DIR/baz"
|
||||||
try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR"
|
try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR"
|
||||||
try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" --components=rustc,cargo,rust-docs
|
try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" \
|
||||||
|
--components=rustc,cargo,rust-docs
|
||||||
try test ! -e "$PREFIX_DIR/bin/program"
|
try test ! -e "$PREFIX_DIR/bin/program"
|
||||||
try test ! -e "$PREFIX_DIR/bin/cargo"
|
try test ! -e "$PREFIX_DIR/bin/cargo"
|
||||||
try test ! -e "$PREFIX_DIR/baz"
|
try test ! -e "$PREFIX_DIR/baz"
|
||||||
|
@ -765,7 +768,8 @@ invalid_component() {
|
||||||
--output-dir="$OUT_DIR" \
|
--output-dir="$OUT_DIR" \
|
||||||
--package-name=rust \
|
--package-name=rust \
|
||||||
--input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz"
|
--input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz"
|
||||||
expect_output_fail "unknown component" "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --components=foo
|
expect_output_fail "unknown component" "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" \
|
||||||
|
--components=foo
|
||||||
}
|
}
|
||||||
runtest invalid_component
|
runtest invalid_component
|
||||||
|
|
||||||
|
|
|
@ -95,17 +95,41 @@ mod os_impl {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: check when rust-installer test sh files will be removed,
|
||||||
|
// and then remove them from exclude list
|
||||||
|
const RI_EXCLUSION_LIST: &[&str] = &[
|
||||||
|
"src/tools/rust-installer/test/image1/bin/program",
|
||||||
|
"src/tools/rust-installer/test/image1/bin/program2",
|
||||||
|
"src/tools/rust-installer/test/image1/bin/bad-bin",
|
||||||
|
"src/tools/rust-installer/test/image2/bin/oldprogram",
|
||||||
|
"src/tools/rust-installer/test/image3/bin/cargo",
|
||||||
|
];
|
||||||
|
|
||||||
|
fn filter_rust_installer_no_so_bins(path: &Path) -> bool {
|
||||||
|
RI_EXCLUSION_LIST.iter().any(|p| path.ends_with(p))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn check(path: &Path, bad: &mut bool) {
|
pub fn check(path: &Path, bad: &mut bool) {
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
|
||||||
const ALLOWED: &[&str] = &["configure", "x"];
|
const ALLOWED: &[&str] = &["configure", "x"];
|
||||||
|
|
||||||
|
for p in RI_EXCLUSION_LIST {
|
||||||
|
if !path.join(Path::new(p)).exists() {
|
||||||
|
tidy_error!(bad, "rust-installer test bins missed: {p}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: we don't need to look at all binaries, only files that have been modified in this branch
|
// FIXME: we don't need to look at all binaries, only files that have been modified in this branch
|
||||||
// (e.g. using `git ls-files`).
|
// (e.g. using `git ls-files`).
|
||||||
walk_no_read(
|
walk_no_read(
|
||||||
&[path],
|
&[path],
|
||||||
|path, _is_dir| filter_dirs(path) || path.ends_with("src/etc"),
|
|path, _is_dir| {
|
||||||
|
filter_dirs(path)
|
||||||
|
|| path.ends_with("src/etc")
|
||||||
|
|| filter_rust_installer_no_so_bins(path)
|
||||||
|
},
|
||||||
&mut |entry| {
|
&mut |entry| {
|
||||||
let file = entry.path();
|
let file = entry.path();
|
||||||
let extension = file.extension();
|
let extension = file.extension();
|
||||||
|
|
|
@ -4,6 +4,8 @@ use std::{ffi::OsStr, fs::File, io::Read, path::Path};
|
||||||
|
|
||||||
/// The default directory filter.
|
/// The default directory filter.
|
||||||
pub fn filter_dirs(path: &Path) -> bool {
|
pub fn filter_dirs(path: &Path) -> bool {
|
||||||
|
// FIXME: sync submodule exclusion list with rustfmt.toml
|
||||||
|
// bootstrap/etc
|
||||||
let skip = [
|
let skip = [
|
||||||
"tidy-test-file",
|
"tidy-test-file",
|
||||||
"compiler/rustc_codegen_cranelift",
|
"compiler/rustc_codegen_cranelift",
|
||||||
|
@ -15,9 +17,7 @@ pub fn filter_dirs(path: &Path) -> bool {
|
||||||
"src/tools/cargo",
|
"src/tools/cargo",
|
||||||
"src/tools/clippy",
|
"src/tools/clippy",
|
||||||
"src/tools/miri",
|
"src/tools/miri",
|
||||||
"src/tools/rls",
|
|
||||||
"src/tools/rust-analyzer",
|
"src/tools/rust-analyzer",
|
||||||
"src/tools/rust-installer",
|
|
||||||
"src/tools/rustfmt",
|
"src/tools/rustfmt",
|
||||||
"src/doc/book",
|
"src/doc/book",
|
||||||
"src/doc/edition-guide",
|
"src/doc/edition-guide",
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
| User Type Annotations
|
| User Type Annotations
|
||||||
| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)]) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
|
| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)]) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
|
||||||
| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated([], DefId(0:8 ~ issue_99325[22bb]::main::{constant#1})) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
|
| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), substs: [] } }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
|
||||||
|
|
|
|
||||||
fn main() -> () {
|
fn main() -> () {
|
||||||
let mut _0: ();
|
let mut _0: ();
|
||||||
|
|
|
@ -24,5 +24,6 @@ fn main() {
|
||||||
type F = impl Future;
|
type F = impl Future;
|
||||||
// Check that statics are inhabited computes they layout.
|
// Check that statics are inhabited computes they layout.
|
||||||
static POOL: Task<F> = Task::new();
|
static POOL: Task<F> = Task::new();
|
||||||
|
//~^ ERROR: cannot check whether the hidden type of `layout_error[b009]::main::F::{opaque#0}` satisfies auto traits
|
||||||
Task::spawn(&POOL, || cb());
|
Task::spawn(&POOL, || cb());
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,24 @@ error[E0425]: cannot find value `Foo` in this scope
|
||||||
LL | let a = Foo;
|
LL | let a = Foo;
|
||||||
| ^^^ not found in this scope
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: cannot check whether the hidden type of `layout_error[b009]::main::F::{opaque#0}` satisfies auto traits
|
||||||
|
--> $DIR/layout-error.rs:26:18
|
||||||
|
|
|
||||||
|
LL | static POOL: Task<F> = Task::new();
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
note: opaque type is declared here
|
||||||
|
--> $DIR/layout-error.rs:24:14
|
||||||
|
|
|
||||||
|
LL | type F = impl Future;
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
note: required because it appears within the type `Task<F>`
|
||||||
|
--> $DIR/layout-error.rs:9:12
|
||||||
|
|
|
||||||
|
LL | pub struct Task<F: Future>(F);
|
||||||
|
| ^^^^
|
||||||
|
= note: shared static variables must have a type that implements `Sync`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0425`.
|
For more information about this error, try `rustc --explain E0425`.
|
||||||
|
|
|
@ -3,21 +3,23 @@ use std::rc::Rc;
|
||||||
|
|
||||||
fn send<T: Send>(_: T) {}
|
fn send<T: Send>(_: T) {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {}
|
||||||
}
|
|
||||||
|
|
||||||
// Cycles should work as the deferred obligations are
|
// Cycles should work as the deferred obligations are
|
||||||
// independently resolved and only require the concrete
|
// independently resolved and only require the concrete
|
||||||
// return type, which can't depend on the obligation.
|
// return type, which can't depend on the obligation.
|
||||||
fn cycle1() -> impl Clone {
|
fn cycle1() -> impl Clone {
|
||||||
//~^ ERROR cycle detected
|
//~^ ERROR cycle detected
|
||||||
|
//~| ERROR cycle detected
|
||||||
send(cycle2().clone());
|
send(cycle2().clone());
|
||||||
|
//~^ ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
|
||||||
|
|
||||||
Rc::new(Cell::new(5))
|
Rc::new(Cell::new(5))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cycle2() -> impl Clone {
|
fn cycle2() -> impl Clone {
|
||||||
send(cycle1().clone());
|
send(cycle1().clone());
|
||||||
|
//~^ ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
|
||||||
|
|
||||||
Rc::new(String::from("foo"))
|
Rc::new(String::from("foo"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
|
error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
|
||||||
--> $DIR/auto-trait-leak.rs:12:16
|
--> $DIR/auto-trait-leak.rs:11:16
|
||||||
|
|
|
|
||||||
LL | fn cycle1() -> impl Clone {
|
LL | fn cycle1() -> impl Clone {
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
@ -11,12 +11,12 @@ LL | send(cycle2().clone());
|
||||||
| ^^^^
|
| ^^^^
|
||||||
= note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`...
|
= note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`...
|
||||||
note: ...which requires computing type of `cycle2::{opaque#0}`...
|
note: ...which requires computing type of `cycle2::{opaque#0}`...
|
||||||
--> $DIR/auto-trait-leak.rs:19:16
|
--> $DIR/auto-trait-leak.rs:20:16
|
||||||
|
|
|
|
||||||
LL | fn cycle2() -> impl Clone {
|
LL | fn cycle2() -> impl Clone {
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
note: ...which requires type-checking `cycle2`...
|
note: ...which requires type-checking `cycle2`...
|
||||||
--> $DIR/auto-trait-leak.rs:20:5
|
--> $DIR/auto-trait-leak.rs:21:5
|
||||||
|
|
|
|
||||||
LL | send(cycle1().clone());
|
LL | send(cycle1().clone());
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
@ -34,6 +34,89 @@ LL | | Rc::new(String::from("foo"))
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
|
||||||
|
--> $DIR/auto-trait-leak.rs:11:16
|
||||||
|
|
|
||||||
|
LL | fn cycle1() -> impl Clone {
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: ...which requires type-checking `cycle1`...
|
||||||
|
--> $DIR/auto-trait-leak.rs:14:5
|
||||||
|
|
|
||||||
|
LL | send(cycle2().clone());
|
||||||
|
| ^^^^
|
||||||
|
= note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`...
|
||||||
|
note: ...which requires computing type of `cycle2::{opaque#0}`...
|
||||||
|
--> $DIR/auto-trait-leak.rs:20:16
|
||||||
|
|
|
||||||
|
LL | fn cycle2() -> impl Clone {
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
note: ...which requires type-checking `cycle2`...
|
||||||
|
--> $DIR/auto-trait-leak.rs:20:1
|
||||||
|
|
|
||||||
|
LL | fn cycle2() -> impl Clone {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
|
||||||
|
note: cycle used when checking item types in top-level module
|
||||||
|
--> $DIR/auto-trait-leak.rs:1:1
|
||||||
|
|
|
||||||
|
LL | / use std::cell::Cell;
|
||||||
|
LL | | use std::rc::Rc;
|
||||||
|
LL | |
|
||||||
|
LL | | fn send<T: Send>(_: T) {}
|
||||||
|
... |
|
||||||
|
LL | | Rc::new(String::from("foo"))
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
||||||
|
error: cannot check whether the hidden type of opaque type satisfies auto traits
|
||||||
|
--> $DIR/auto-trait-leak.rs:21:10
|
||||||
|
|
|
||||||
|
LL | send(cycle1().clone());
|
||||||
|
| ---- ^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
note: opaque type is declared here
|
||||||
|
--> $DIR/auto-trait-leak.rs:11:16
|
||||||
|
|
|
||||||
|
LL | fn cycle1() -> impl Clone {
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
|
||||||
|
--> $DIR/auto-trait-leak.rs:20:4
|
||||||
|
|
|
||||||
|
LL | fn cycle2() -> impl Clone {
|
||||||
|
| ^^^^^^
|
||||||
|
note: required by a bound in `send`
|
||||||
|
--> $DIR/auto-trait-leak.rs:4:12
|
||||||
|
|
|
||||||
|
LL | fn send<T: Send>(_: T) {}
|
||||||
|
| ^^^^ required by this bound in `send`
|
||||||
|
|
||||||
|
error: cannot check whether the hidden type of opaque type satisfies auto traits
|
||||||
|
--> $DIR/auto-trait-leak.rs:14:10
|
||||||
|
|
|
||||||
|
LL | send(cycle2().clone());
|
||||||
|
| ---- ^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
note: opaque type is declared here
|
||||||
|
--> $DIR/auto-trait-leak.rs:20:16
|
||||||
|
|
|
||||||
|
LL | fn cycle2() -> impl Clone {
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
|
||||||
|
--> $DIR/auto-trait-leak.rs:11:4
|
||||||
|
|
|
||||||
|
LL | fn cycle1() -> impl Clone {
|
||||||
|
| ^^^^^^
|
||||||
|
note: required by a bound in `send`
|
||||||
|
--> $DIR/auto-trait-leak.rs:4:12
|
||||||
|
|
|
||||||
|
LL | fn send<T: Send>(_: T) {}
|
||||||
|
| ^^^^ required by this bound in `send`
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0391`.
|
For more information about this error, try `rustc --explain E0391`.
|
||||||
|
|
|
@ -24,6 +24,8 @@ where
|
||||||
B: Send, // <- a second bound
|
B: Send, // <- a second bound
|
||||||
{
|
{
|
||||||
normalize(broken_fut(), ());
|
normalize(broken_fut(), ());
|
||||||
|
//~^ ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
|
||||||
|
//~| ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -4,6 +4,61 @@ error[E0425]: cannot find value `ident_error` in this scope
|
||||||
LL | ident_error;
|
LL | ident_error;
|
||||||
| ^^^^^^^^^^^ not found in this scope
|
| ^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: cannot check whether the hidden type of opaque type satisfies auto traits
|
||||||
|
--> $DIR/issue-103181-2.rs:26:15
|
||||||
|
|
|
||||||
|
LL | normalize(broken_fut(), ());
|
||||||
|
| --------- ^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
note: opaque type is declared here
|
||||||
|
--> $DIR/issue-103181-2.rs:11:23
|
||||||
|
|
|
||||||
|
LL | async fn broken_fut() {
|
||||||
|
| ^
|
||||||
|
note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
|
||||||
|
--> $DIR/issue-103181-2.rs:20:10
|
||||||
|
|
|
||||||
|
LL | async fn iceice<A, B>()
|
||||||
|
| ^^^^^^
|
||||||
|
note: required for `impl Future<Output = ()>` to implement `SendFuture`
|
||||||
|
--> $DIR/issue-103181-2.rs:7:17
|
||||||
|
|
|
||||||
|
LL | impl<Fut: Send> SendFuture for Fut {
|
||||||
|
| ---- ^^^^^^^^^^ ^^^
|
||||||
|
| |
|
||||||
|
| unsatisfied trait bound introduced here
|
||||||
|
note: required by a bound in `normalize`
|
||||||
|
--> $DIR/issue-103181-2.rs:18:19
|
||||||
|
|
|
||||||
|
LL | fn normalize<Fut: SendFuture>(_: Fut, _: Fut::Output) {}
|
||||||
|
| ^^^^^^^^^^ required by this bound in `normalize`
|
||||||
|
|
||||||
|
error: cannot check whether the hidden type of opaque type satisfies auto traits
|
||||||
|
--> $DIR/issue-103181-2.rs:26:5
|
||||||
|
|
|
||||||
|
LL | normalize(broken_fut(), ());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: opaque type is declared here
|
||||||
|
--> $DIR/issue-103181-2.rs:11:23
|
||||||
|
|
|
||||||
|
LL | async fn broken_fut() {
|
||||||
|
| ^
|
||||||
|
note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
|
||||||
|
--> $DIR/issue-103181-2.rs:20:10
|
||||||
|
|
|
||||||
|
LL | async fn iceice<A, B>()
|
||||||
|
| ^^^^^^
|
||||||
|
note: required for `impl Future<Output = ()>` to implement `SendFuture`
|
||||||
|
--> $DIR/issue-103181-2.rs:7:17
|
||||||
|
|
|
||||||
|
LL | impl<Fut: Send> SendFuture for Fut {
|
||||||
|
| ---- ^^^^^^^^^^ ^^^
|
||||||
|
| |
|
||||||
|
| unsatisfied trait bound introduced here
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0425`.
|
For more information about this error, try `rustc --explain E0425`.
|
||||||
|
|
22
tests/ui/traits/new-solver/winnow-specializing-impls.rs
Normal file
22
tests/ui/traits/new-solver/winnow-specializing-impls.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// build-pass
|
||||||
|
// compile-flags: -Ztrait-solver=next
|
||||||
|
|
||||||
|
// Tests that the specializing impl `<() as Foo>` holds during codegen.
|
||||||
|
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
fn bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Foo for T {
|
||||||
|
default fn bar() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for () {
|
||||||
|
fn bar() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
<() as Foo>::bar();
|
||||||
|
}
|
|
@ -4,8 +4,9 @@
|
||||||
// FIXME This should compile, but it currently doesn't
|
// FIXME This should compile, but it currently doesn't
|
||||||
|
|
||||||
mod m {
|
mod m {
|
||||||
type Foo = impl std::fmt::Debug;
|
pub type Foo = impl std::fmt::Debug;
|
||||||
//~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
|
//~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
|
||||||
|
//~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
|
||||||
|
|
||||||
pub fn foo() -> Foo {
|
pub fn foo() -> Foo {
|
||||||
22_u32
|
22_u32
|
||||||
|
@ -13,6 +14,7 @@ mod m {
|
||||||
|
|
||||||
pub fn bar() {
|
pub fn bar() {
|
||||||
is_send(foo());
|
is_send(foo());
|
||||||
|
//~^ ERROR: cannot check whether the hidden type of `auto_trait_leakage3[211d]::m::Foo::{opaque#0}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_send<T: Send>(_: T) {}
|
fn is_send<T: Send>(_: T) {}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
|
error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
|
||||||
--> $DIR/auto-trait-leakage3.rs:7:16
|
--> $DIR/auto-trait-leakage3.rs:7:20
|
||||||
|
|
|
|
||||||
LL | type Foo = impl std::fmt::Debug;
|
LL | pub type Foo = impl std::fmt::Debug;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires type-checking `m::bar`...
|
note: ...which requires type-checking `m::bar`...
|
||||||
--> $DIR/auto-trait-leakage3.rs:15:9
|
--> $DIR/auto-trait-leakage3.rs:16:9
|
||||||
|
|
|
|
||||||
LL | is_send(foo());
|
LL | is_send(foo());
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
@ -17,6 +17,48 @@ note: cycle used when checking item types in module `m`
|
||||||
LL | mod m {
|
LL | mod m {
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
|
||||||
|
--> $DIR/auto-trait-leakage3.rs:7:20
|
||||||
|
|
|
||||||
|
LL | pub type Foo = impl std::fmt::Debug;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: ...which requires type-checking `m::bar`...
|
||||||
|
--> $DIR/auto-trait-leakage3.rs:15:5
|
||||||
|
|
|
||||||
|
LL | pub fn bar() {
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
= note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
|
||||||
|
note: cycle used when checking item types in module `m`
|
||||||
|
--> $DIR/auto-trait-leakage3.rs:6:1
|
||||||
|
|
|
||||||
|
LL | mod m {
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: cannot check whether the hidden type of `auto_trait_leakage3[211d]::m::Foo::{opaque#0}` satisfies auto traits
|
||||||
|
--> $DIR/auto-trait-leakage3.rs:16:17
|
||||||
|
|
|
||||||
|
LL | is_send(foo());
|
||||||
|
| ------- ^^^^^
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
note: opaque type is declared here
|
||||||
|
--> $DIR/auto-trait-leakage3.rs:7:20
|
||||||
|
|
|
||||||
|
LL | pub type Foo = impl std::fmt::Debug;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
|
||||||
|
--> $DIR/auto-trait-leakage3.rs:15:12
|
||||||
|
|
|
||||||
|
LL | pub fn bar() {
|
||||||
|
| ^^^
|
||||||
|
note: required by a bound in `is_send`
|
||||||
|
--> $DIR/auto-trait-leakage3.rs:20:19
|
||||||
|
|
|
||||||
|
LL | fn is_send<T: Send>(_: T) {}
|
||||||
|
| ^^^^ required by this bound in `is_send`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0391`.
|
For more information about this error, try `rustc --explain E0391`.
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
mod m {
|
mod m {
|
||||||
type Foo = impl std::fmt::Debug;
|
pub type Foo = impl std::fmt::Debug;
|
||||||
//~^ ERROR cycle detected
|
//~^ ERROR cycle detected
|
||||||
|
//~| ERROR cycle detected
|
||||||
|
|
||||||
// Cycle: error today, but it'd be nice if it eventually worked
|
// Cycle: error today, but it'd be nice if it eventually worked
|
||||||
|
|
||||||
|
@ -13,10 +14,11 @@ mod m {
|
||||||
|
|
||||||
pub fn bar() {
|
pub fn bar() {
|
||||||
is_send(foo()); // Today: error
|
is_send(foo()); // Today: error
|
||||||
|
//~^ ERROR: cannot check whether the hidden type of `inference_cycle[4ecc]::m::Foo::{opaque#0}` satisfies auto traits
|
||||||
}
|
}
|
||||||
|
|
||||||
fn baz() {
|
fn baz() {
|
||||||
let f: Foo = 22_u32;
|
let f: Foo = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_send<T: Send>(_: T) {}
|
fn is_send<T: Send>(_: T) {}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
|
error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
|
||||||
--> $DIR/inference-cycle.rs:5:16
|
--> $DIR/inference-cycle.rs:5:20
|
||||||
|
|
|
|
||||||
LL | type Foo = impl std::fmt::Debug;
|
LL | pub type Foo = impl std::fmt::Debug;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires type-checking `m::bar`...
|
note: ...which requires type-checking `m::bar`...
|
||||||
--> $DIR/inference-cycle.rs:15:9
|
--> $DIR/inference-cycle.rs:16:9
|
||||||
|
|
|
|
||||||
LL | is_send(foo()); // Today: error
|
LL | is_send(foo()); // Today: error
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
@ -17,6 +17,48 @@ note: cycle used when checking item types in module `m`
|
||||||
LL | mod m {
|
LL | mod m {
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
|
||||||
|
--> $DIR/inference-cycle.rs:5:20
|
||||||
|
|
|
||||||
|
LL | pub type Foo = impl std::fmt::Debug;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: ...which requires type-checking `m::bar`...
|
||||||
|
--> $DIR/inference-cycle.rs:15:5
|
||||||
|
|
|
||||||
|
LL | pub fn bar() {
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
= note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
|
||||||
|
note: cycle used when checking item types in module `m`
|
||||||
|
--> $DIR/inference-cycle.rs:4:1
|
||||||
|
|
|
||||||
|
LL | mod m {
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: cannot check whether the hidden type of `inference_cycle[4ecc]::m::Foo::{opaque#0}` satisfies auto traits
|
||||||
|
--> $DIR/inference-cycle.rs:16:17
|
||||||
|
|
|
||||||
|
LL | is_send(foo()); // Today: error
|
||||||
|
| ------- ^^^^^
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
note: opaque type is declared here
|
||||||
|
--> $DIR/inference-cycle.rs:5:20
|
||||||
|
|
|
||||||
|
LL | pub type Foo = impl std::fmt::Debug;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
|
||||||
|
--> $DIR/inference-cycle.rs:15:12
|
||||||
|
|
|
||||||
|
LL | pub fn bar() {
|
||||||
|
| ^^^
|
||||||
|
note: required by a bound in `is_send`
|
||||||
|
--> $DIR/inference-cycle.rs:24:19
|
||||||
|
|
|
||||||
|
LL | fn is_send<T: Send>(_: T) {}
|
||||||
|
| ^^^^ required by this bound in `is_send`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0391`.
|
For more information about this error, try `rustc --explain E0391`.
|
||||||
|
|
|
@ -4,13 +4,16 @@ use std::fmt::Debug;
|
||||||
|
|
||||||
type Foo = impl Debug;
|
type Foo = impl Debug;
|
||||||
//~^ ERROR cycle detected
|
//~^ ERROR cycle detected
|
||||||
|
//~| ERROR cycle detected
|
||||||
|
//~| ERROR cycle detected
|
||||||
|
|
||||||
fn is_send<T: Send>() { }
|
fn is_send<T: Send>() {}
|
||||||
|
|
||||||
fn not_good() {
|
fn not_good() {
|
||||||
// Error: this function does not constrain `Foo` to any particular
|
// Error: this function does not constrain `Foo` to any particular
|
||||||
// hidden type, so it cannot rely on `Send` being true.
|
// hidden type, so it cannot rely on `Send` being true.
|
||||||
is_send::<Foo>();
|
is_send::<Foo>();
|
||||||
|
//~^ ERROR: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
|
||||||
}
|
}
|
||||||
|
|
||||||
fn not_gooder() {
|
fn not_gooder() {
|
||||||
|
@ -20,6 +23,7 @@ fn not_gooder() {
|
||||||
// while we could know this from the hidden type, it would
|
// while we could know this from the hidden type, it would
|
||||||
// need extra roundabout logic to support it.
|
// need extra roundabout logic to support it.
|
||||||
is_send::<Foo>();
|
is_send::<Foo>();
|
||||||
|
//~^ ERROR: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -5,7 +5,7 @@ LL | type Foo = impl Debug;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires type-checking `not_good`...
|
note: ...which requires type-checking `not_good`...
|
||||||
--> $DIR/reveal_local.rs:13:5
|
--> $DIR/reveal_local.rs:15:5
|
||||||
|
|
|
|
||||||
LL | is_send::<Foo>();
|
LL | is_send::<Foo>();
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
@ -23,6 +23,98 @@ LL | |
|
||||||
LL | | fn main() {}
|
LL | | fn main() {}
|
||||||
| |____________^
|
| |____________^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
|
||||||
|
--> $DIR/reveal_local.rs:5:12
|
||||||
|
|
|
||||||
|
LL | type Foo = impl Debug;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: ...which requires type-checking `not_good`...
|
||||||
|
--> $DIR/reveal_local.rs:12:1
|
||||||
|
|
|
||||||
|
LL | fn not_good() {
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
= note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
|
||||||
|
note: cycle used when checking item types in top-level module
|
||||||
|
--> $DIR/reveal_local.rs:1:1
|
||||||
|
|
|
||||||
|
LL | / #![feature(type_alias_impl_trait)]
|
||||||
|
LL | |
|
||||||
|
LL | | use std::fmt::Debug;
|
||||||
|
LL | |
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | fn main() {}
|
||||||
|
| |____________^
|
||||||
|
|
||||||
|
error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
|
||||||
|
--> $DIR/reveal_local.rs:15:15
|
||||||
|
|
|
||||||
|
LL | is_send::<Foo>();
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
note: opaque type is declared here
|
||||||
|
--> $DIR/reveal_local.rs:5:12
|
||||||
|
|
|
||||||
|
LL | type Foo = impl Debug;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
|
||||||
|
--> $DIR/reveal_local.rs:12:4
|
||||||
|
|
|
||||||
|
LL | fn not_good() {
|
||||||
|
| ^^^^^^^^
|
||||||
|
note: required by a bound in `is_send`
|
||||||
|
--> $DIR/reveal_local.rs:10:15
|
||||||
|
|
|
||||||
|
LL | fn is_send<T: Send>() {}
|
||||||
|
| ^^^^ required by this bound in `is_send`
|
||||||
|
|
||||||
|
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
|
||||||
|
--> $DIR/reveal_local.rs:5:12
|
||||||
|
|
|
||||||
|
LL | type Foo = impl Debug;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: ...which requires type-checking `not_gooder`...
|
||||||
|
--> $DIR/reveal_local.rs:19:1
|
||||||
|
|
|
||||||
|
LL | fn not_gooder() {
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
= note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
|
||||||
|
note: cycle used when checking item types in top-level module
|
||||||
|
--> $DIR/reveal_local.rs:1:1
|
||||||
|
|
|
||||||
|
LL | / #![feature(type_alias_impl_trait)]
|
||||||
|
LL | |
|
||||||
|
LL | | use std::fmt::Debug;
|
||||||
|
LL | |
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | fn main() {}
|
||||||
|
| |____________^
|
||||||
|
|
||||||
|
error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
|
||||||
|
--> $DIR/reveal_local.rs:25:15
|
||||||
|
|
|
||||||
|
LL | is_send::<Foo>();
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
note: opaque type is declared here
|
||||||
|
--> $DIR/reveal_local.rs:5:12
|
||||||
|
|
|
||||||
|
LL | type Foo = impl Debug;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
|
||||||
|
--> $DIR/reveal_local.rs:19:4
|
||||||
|
|
|
||||||
|
LL | fn not_gooder() {
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
note: required by a bound in `is_send`
|
||||||
|
--> $DIR/reveal_local.rs:10:15
|
||||||
|
|
|
||||||
|
LL | fn is_send<T: Send>() {}
|
||||||
|
| ^^^^ required by this bound in `is_send`
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0391`.
|
For more information about this error, try `rustc --explain E0391`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue