Auto merge of #77224 - RalfJung:rollup-hdvb96c, r=RalfJung

Rollup of 12 pull requests

Successful merges:

 - #75454 (Explicitly document the size guarantees that Option makes.)
 - #76631 (Add `x.py setup`)
 - #77076 (Add missing code examples on slice iter types)
 - #77093 (merge `need_type_info_err(_const)`)
 - #77122 (Add `#![feature(const_fn_floating_point_arithmetic)]`)
 - #77127 (Update mdBook)
 - #77161 (Remove TrustedLen requirement from BuilderMethods::switch)
 - #77166 (update Miri)
 - #77181 (Add doc alias for pointer primitive)
 - #77204 (Remove stray word from `ClosureKind::extends` docs)
 - #77207 (Rename `whence` to `span`)
 - #77211 (Remove unused #[allow(...)] statements from compiler/)

Failed merges:

 - #77170 (Remove `#[rustc_allow_const_fn_ptr]` and add `#![feature(const_fn_fn_ptr_basics)]`)

r? `@ghost`
This commit is contained in:
bors
2020-09-26 17:50:26 +00:00
74 changed files with 808 additions and 342 deletions
+2 -2
View File
@@ -1848,9 +1848,9 @@ dependencies = [
[[package]]
name = "mdbook"
version = "0.4.2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b75e31ae4eaa0e45e17ee2b6b9e3ed969c3c6ff12bb4c2e352c42493f4ebb706"
checksum = "29be448fcafb00c5a8966c4020c2a5ffbbc333e5b96d0bb5ef54b5bd0524d9ff"
dependencies = [
"ammonia",
"anyhow",
-1
View File
@@ -15,7 +15,6 @@
#![feature(new_uninit)]
#![feature(maybe_uninit_slice)]
#![cfg_attr(test, feature(test))]
#![allow(deprecated)]
use rustc_data_structures::cold_path;
use smallvec::SmallVec;
+1 -3
View File
@@ -21,7 +21,6 @@
use rustc_target::spec::{HasTargetSpec, Target};
use std::borrow::Cow;
use std::ffi::CStr;
use std::iter::TrustedLen;
use std::ops::{Deref, Range};
use std::ptr;
use tracing::debug;
@@ -179,7 +178,7 @@ fn switch(
&mut self,
v: &'ll Value,
else_llbb: &'ll BasicBlock,
cases: impl ExactSizeIterator<Item = (u128, &'ll BasicBlock)> + TrustedLen,
cases: impl ExactSizeIterator<Item = (u128, &'ll BasicBlock)>,
) {
let switch =
unsafe { llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, cases.len() as c_uint) };
@@ -931,7 +930,6 @@ fn select(
unsafe { llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, UNNAMED) }
}
#[allow(dead_code)]
fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) }
}
@@ -1,5 +1,3 @@
#![allow(non_camel_case_types, non_snake_case)]
//! Code that is useful in various codegen modules.
use crate::consts::{self, const_alloc_to_llvm};
@@ -1845,7 +1845,6 @@ fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option<SourceInfo<'ll>> {
None
}
#[allow(dead_code)]
fn is_artificial(&self) -> bool {
match self {
VariantInfo::Generator { .. } => true,
-1
View File
@@ -12,7 +12,6 @@
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(or_patterns)]
#![feature(trusted_len)]
#![recursion_limit = "256"]
use back::write::{create_informational_target_machine, create_target_machine};
@@ -11,7 +11,6 @@
use rustc_middle::ty::Ty;
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size};
#[allow(dead_code)]
fn round_pointer_up_to_alignment(
bx: &mut Builder<'a, 'll, 'tcx>,
addr: &'ll Value,
+1 -3
View File
@@ -1,4 +1,4 @@
#![allow(non_camel_case_types, non_snake_case)]
#![allow(non_camel_case_types)]
use rustc_errors::struct_span_err;
use rustc_hir as hir;
@@ -25,7 +25,6 @@ pub enum IntPredicate {
IntSLE,
}
#[allow(dead_code)]
pub enum RealPredicate {
RealPredicateFalse,
RealOEQ,
@@ -60,7 +59,6 @@ pub enum AtomicRmwBinOp {
}
pub enum AtomicOrdering {
#[allow(dead_code)]
NotAtomic,
Unordered,
Monotonic,
-1
View File
@@ -6,7 +6,6 @@
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(or_patterns)]
#![feature(trusted_len)]
#![feature(associated_type_bounds)]
#![recursion_limit = "256"]
@@ -18,7 +18,6 @@
use rustc_target::abi::{Abi, Align, Scalar, Size};
use rustc_target::spec::HasTargetSpec;
use std::iter::TrustedLen;
use std::ops::Range;
#[derive(Copy, Clone)]
@@ -60,7 +59,7 @@ fn switch(
&mut self,
v: Self::Value,
else_llbb: Self::BasicBlock,
cases: impl ExactSizeIterator<Item = (u128, Self::BasicBlock)> + TrustedLen,
cases: impl ExactSizeIterator<Item = (u128, Self::BasicBlock)>,
);
fn invoke(
&mut self,
@@ -7,7 +7,6 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![allow(incomplete_features)]
#![feature(array_windows)]
#![feature(control_flow_enum)]
#![feature(in_band_lifetimes)]
+3
View File
@@ -584,6 +584,9 @@ pub fn set(&self, features: &mut Features, span: Span) {
/// Allows non trivial generic constants which have to be manually propageted upwards.
(active, const_evaluatable_checked, "1.48.0", Some(76560), None),
/// Allows basic arithmetic on floating point types in a `const fn`.
(active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None),
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
-3
View File
@@ -256,7 +256,6 @@ pub trait Visitor<'v>: Sized {
/// patterns described on `itemlikevisit::ItemLikeVisitor`. The only
/// reason to override this method is if you want a nested pattern
/// but cannot supply a `Map`; see `nested_visit_map` for advice.
#[allow(unused_variables)]
fn visit_nested_item(&mut self, id: ItemId) {
let opt_item = self.nested_visit_map().inter().map(|map| map.item(id.id));
walk_list!(self, visit_item, opt_item);
@@ -265,7 +264,6 @@ fn visit_nested_item(&mut self, id: ItemId) {
/// Like `visit_nested_item()`, but for trait items. See
/// `visit_nested_item()` for advice on when to override this
/// method.
#[allow(unused_variables)]
fn visit_nested_trait_item(&mut self, id: TraitItemId) {
let opt_item = self.nested_visit_map().inter().map(|map| map.trait_item(id));
walk_list!(self, visit_trait_item, opt_item);
@@ -274,7 +272,6 @@ fn visit_nested_trait_item(&mut self, id: TraitItemId) {
/// Like `visit_nested_item()`, but for impl items. See
/// `visit_nested_item()` for advice on when to override this
/// method.
#[allow(unused_variables)]
fn visit_nested_impl_item(&mut self, id: ImplItemId) {
let opt_item = self.nested_visit_map().inter().map(|map| map.impl_item(id));
walk_list!(self, visit_impl_item, opt_item);
@@ -176,7 +176,10 @@ fn closure_return_type_suggestion(
suggestion,
Applicability::HasPlaceholders,
);
err.span_label(span, InferCtxt::missing_type_msg(&name, &descr, parent_name, parent_descr));
err.span_label(
span,
InferCtxt::cannot_infer_msg("type", &name, &descr, parent_name, parent_descr),
);
}
/// Given a closure signature, return a `String` containing a list of all its argument types.
@@ -217,65 +220,151 @@ fn into(self) -> rustc_errors::DiagnosticId {
}
}
/// Information about a constant or a type containing inference variables.
pub struct InferenceDiagnosticsData {
pub name: String,
pub span: Option<Span>,
pub description: Cow<'static, str>,
pub parent_name: Option<String>,
pub parent_description: Option<&'static str>,
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn extract_type_name(
/// Extracts data used by diagnostic for either types or constants
/// which were stuck during inference.
pub fn extract_inference_diagnostics_data(
&self,
ty: Ty<'tcx>,
arg: GenericArg<'tcx>,
highlight: Option<ty::print::RegionHighlightMode>,
) -> (String, Option<Span>, Cow<'static, str>, Option<String>, Option<&'static str>) {
if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
let mut inner = self.inner.borrow_mut();
let ty_vars = &inner.type_variables();
let var_origin = ty_vars.var_origin(ty_vid);
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind {
let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
let (parent_name, parent_desc) = if let Some(parent_def_id) = parent_def_id {
let parent_name = self
.tcx
.def_key(parent_def_id)
.disambiguated_data
.data
.get_opt_name()
.map(|parent_symbol| parent_symbol.to_string());
) -> InferenceDiagnosticsData {
match arg.unpack() {
GenericArgKind::Type(ty) => {
if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
let mut inner = self.inner.borrow_mut();
let ty_vars = &inner.type_variables();
let var_origin = ty_vars.var_origin(ty_vid);
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) =
var_origin.kind
{
let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
let (parent_name, parent_description) =
if let Some(parent_def_id) = parent_def_id {
let parent_name = self
.tcx
.def_key(parent_def_id)
.disambiguated_data
.data
.get_opt_name()
.map(|parent_symbol| parent_symbol.to_string());
(parent_name, Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)))
} else {
(None, None)
};
(
parent_name,
Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
)
} else {
(None, None)
};
if name != kw::SelfUpper {
return (
name.to_string(),
Some(var_origin.span),
"type parameter".into(),
parent_name,
parent_desc,
);
if name != kw::SelfUpper {
return InferenceDiagnosticsData {
name: name.to_string(),
span: Some(var_origin.span),
description: "type parameter".into(),
parent_name,
parent_description,
};
}
}
}
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
if let Some(highlight) = highlight {
printer.region_highlight_mode = highlight;
}
let _ = ty.print(printer);
InferenceDiagnosticsData {
name: s,
span: None,
description: ty.prefix_string(),
parent_name: None,
parent_description: None,
}
}
}
GenericArgKind::Const(ct) => {
if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
let origin =
self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
origin.kind
{
let parent_def_id = self.tcx.parent(def_id);
let (parent_name, parent_description) =
if let Some(parent_def_id) = parent_def_id {
let parent_name = self
.tcx
.def_key(parent_def_id)
.disambiguated_data
.data
.get_opt_name()
.map(|parent_symbol| parent_symbol.to_string());
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
if let Some(highlight) = highlight {
printer.region_highlight_mode = highlight;
(
parent_name,
Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
)
} else {
(None, None)
};
return InferenceDiagnosticsData {
name: name.to_string(),
span: Some(origin.span),
description: "const parameter".into(),
parent_name,
parent_description,
};
}
debug_assert!(!origin.span.is_dummy());
let mut s = String::new();
let mut printer =
ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS);
if let Some(highlight) = highlight {
printer.region_highlight_mode = highlight;
}
let _ = ct.print(printer);
InferenceDiagnosticsData {
name: s,
span: Some(origin.span),
description: "the constant".into(),
parent_name: None,
parent_description: None,
}
} else {
bug!("unexpect const: {:?}", ct);
}
}
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
}
let _ = ty.print(printer);
(s, None, ty.prefix_string(), None, None)
}
// FIXME(eddyb) generalize all of this to handle `ty::Const` inference variables as well.
pub fn need_type_info_err(
pub fn emit_inference_failure_err(
&self,
body_id: Option<hir::BodyId>,
span: Span,
ty: Ty<'tcx>,
arg: GenericArg<'tcx>,
error_code: TypeAnnotationNeeded,
) -> DiagnosticBuilder<'tcx> {
let ty = self.resolve_vars_if_possible(&ty);
let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None);
let arg = self.resolve_vars_if_possible(&arg);
let arg_data = self.extract_inference_diagnostics_data(arg, None);
let kind_str = match arg.unpack() {
GenericArgKind::Type(_) => "type",
GenericArgKind::Const(_) => "the value",
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
};
let mut local_visitor = FindHirNodeVisitor::new(&self, ty.into(), span);
let mut local_visitor = FindHirNodeVisitor::new(&self, arg, span);
let ty_to_string = |ty: Ty<'tcx>| -> String {
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
@@ -305,7 +394,7 @@ pub fn need_type_info_err(
}
let err_span = if let Some(pattern) = local_visitor.found_arg_pattern {
pattern.span
} else if let Some(span) = name_sp {
} else if let Some(span) = arg_data.span {
// `span` here lets us point at `sum` instead of the entire right hand side expr:
// error[E0282]: type annotations needed
// --> file2.rs:3:15
@@ -352,7 +441,7 @@ pub fn need_type_info_err(
_ => String::new(),
};
// When `name` corresponds to a type argument, show the path of the full type we're
// When `arg_data.name` corresponds to a type argument, show the path of the full type we're
// trying to infer. In the following example, `ty_msg` contains
// " in `std::result::Result<i32, E>`":
// ```
@@ -391,11 +480,11 @@ pub fn need_type_info_err(
&mut err,
&decl.output,
self.tcx.hir().body(body_id),
&descr,
&name,
&arg_data.description,
&arg_data.name,
&ret,
parent_name,
parent_descr,
arg_data.parent_name,
arg_data.parent_description,
);
// We don't want to give the other suggestions when the problem is the
// closure return type.
@@ -409,15 +498,15 @@ pub fn need_type_info_err(
// nudge them in the right direction.
format!("a boxed closure type like `Box<dyn Fn({}) -> {}>`", args, ret)
}
Some(ty) if is_named_and_not_impl_trait(ty) && name == "_" => {
Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => {
let ty = ty_to_string(ty);
format!("the explicit type `{}`, with the type parameters specified", ty)
}
Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != name => {
Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => {
let ty = ty_to_string(ty);
format!(
"the explicit type `{}`, where the type parameter `{}` is specified",
ty, name,
ty, arg_data.name,
)
}
_ => "a type".to_string(),
@@ -534,7 +623,7 @@ pub fn need_type_info_err(
// | ^^^ cannot infer type for `S`
// |
// = note: type must be known at this point
let span = name_sp.unwrap_or(err_span);
let span = arg_data.span.unwrap_or(err_span);
if !err
.span
.span_labels()
@@ -545,55 +634,19 @@ pub fn need_type_info_err(
// Avoid multiple labels pointing at `span`.
err.span_label(
span,
InferCtxt::missing_type_msg(&name, &descr, parent_name, parent_descr),
InferCtxt::cannot_infer_msg(
kind_str,
&arg_data.name,
&arg_data.description,
arg_data.parent_name,
arg_data.parent_description,
),
);
}
err
}
// FIXME(const_generics): We should either try and merge this with `need_type_info_err`
// or improve the errors created here.
//
// Unlike for type inference variables, we don't yet store the origin of const inference variables.
// This is needed for to get a more relevant error span.
pub fn need_type_info_err_const(
&self,
body_id: Option<hir::BodyId>,
span: Span,
ct: &'tcx ty::Const<'tcx>,
error_code: TypeAnnotationNeeded,
) -> DiagnosticBuilder<'tcx> {
let mut local_visitor = FindHirNodeVisitor::new(&self, ct.into(), span);
if let Some(body_id) = body_id {
let expr = self.tcx.hir().expect_expr(body_id.hir_id);
local_visitor.visit_expr(expr);
}
let mut param_name = None;
let span = if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
let origin = self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
if let ConstVariableOriginKind::ConstParameterDefinition(param) = origin.kind {
param_name = Some(param);
}
origin.span
} else {
local_visitor.target_span
};
let error_code = error_code.into();
let mut err =
self.tcx.sess.struct_span_err_with_code(span, "type annotations needed", error_code);
if let Some(param_name) = param_name {
err.note(&format!("cannot infer the value of the const parameter `{}`", param_name));
} else {
err.note("unable to infer the value of a const parameter");
}
err
}
/// If the `FnSig` for the method call can be found and type arguments are identified as
/// needed, suggest annotating the call, otherwise point out the resulting type of the call.
fn annotate_method_call(
@@ -647,7 +700,7 @@ pub fn need_type_info_err_in_generator(
ty: Ty<'tcx>,
) -> DiagnosticBuilder<'tcx> {
let ty = self.resolve_vars_if_possible(&ty);
let (name, _, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None);
let data = self.extract_inference_diagnostics_data(ty.into(), None);
let mut err = struct_span_err!(
self.tcx.sess,
@@ -656,18 +709,28 @@ pub fn need_type_info_err_in_generator(
"type inside {} must be known in this context",
kind,
);
err.span_label(span, InferCtxt::missing_type_msg(&name, &descr, parent_name, parent_descr));
err.span_label(
span,
InferCtxt::cannot_infer_msg(
"type",
&data.name,
&data.description,
data.parent_name,
data.parent_description,
),
);
err
}
fn missing_type_msg(
fn cannot_infer_msg(
kind_str: &str,
type_name: &str,
descr: &str,
parent_name: Option<String>,
parent_descr: Option<&str>,
) -> Cow<'static, str> {
) -> String {
if type_name == "_" {
"cannot infer type".into()
format!("cannot infer {}", kind_str)
} else {
let parent_desc = if let Some(parent_name) = parent_name {
let parent_type_descr = if let Some(parent_descr) = parent_descr {
@@ -681,7 +744,15 @@ fn missing_type_msg(
"".to_string()
};
format!("cannot infer type for {} `{}`{}", descr, type_name, parent_desc).into()
// FIXME: We really shouldn't be dealing with strings here
// but instead use a sensible enum for cases like this.
let preposition = if "the value" == kind_str { "of" } else { "for" };
// For example: "cannot infer type for type parameter `T`"
format!(
"cannot infer {} {} {} `{}`{}",
kind_str, preposition, descr, type_name, parent_desc
)
.into()
}
}
}
+4 -2
View File
@@ -1163,7 +1163,10 @@ pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef) -> GenericArg
}
GenericParamDefKind::Const { .. } => {
let origin = ConstVariableOrigin {
kind: ConstVariableOriginKind::ConstParameterDefinition(param.name),
kind: ConstVariableOriginKind::ConstParameterDefinition(
param.name,
param.def_id,
),
span,
};
let const_var_id =
@@ -1275,7 +1278,6 @@ pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
}
/// Gives temporary access to the region constraint data.
#[allow(non_camel_case_types)] // bug with impl trait
pub fn with_region_constraints<R>(
&self,
op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
-2
View File
@@ -1,5 +1,3 @@
#![allow(non_snake_case)]
use crate::{LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
use rustc_attr as attr;
-1
View File
@@ -21,7 +21,6 @@ pub fn len(&self) -> usize {
/// Appending to a Rust string -- used by RawRustStringOstream.
#[no_mangle]
#[allow(improper_ctypes_definitions)]
pub unsafe extern "C" fn LLVMRustStringWriteImpl(
sr: &RustString,
ptr: *const c_char,
-1
View File
@@ -9,7 +9,6 @@
ReturnType, Token, Type,
};
#[allow(non_camel_case_types)]
mod kw {
syn::custom_keyword!(query);
}
-1
View File
@@ -4,7 +4,6 @@
use syn::parse::{Parse, ParseStream, Result};
use syn::{braced, parse_macro_input, Ident, LitStr, Token};
#[allow(non_camel_case_types)]
mod kw {
syn::custom_keyword!(Keywords);
syn::custom_keyword!(Symbols);
+9 -9
View File
@@ -4,8 +4,9 @@
use rustc_data_structures::unify::{
self, EqUnifyValue, InPlace, NoError, UnificationTable, UnifyKey, UnifyValue,
};
use rustc_span::def_id::DefId;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use rustc_span::Span;
use std::cmp;
use std::marker::PhantomData;
@@ -124,8 +125,7 @@ pub struct ConstVariableOrigin {
pub enum ConstVariableOriginKind {
MiscVariable,
ConstInference,
// FIXME(const_generics): Consider storing the `DefId` of the param here.
ConstParameterDefinition(Symbol),
ConstParameterDefinition(Symbol, DefId),
SubstitutionPlaceholder,
}
@@ -176,17 +176,17 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
type Error = (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>);
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
let val = match (value1.val, value2.val) {
let (val, span) = match (value1.val, value2.val) {
(ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => {
bug!("equating two const variables, both of which have known values")
}
// If one side is known, prefer that one.
(ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => {
Ok(value1.val)
(value1.val, value1.origin.span)
}
(ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => {
Ok(value2.val)
(value2.val, value2.origin.span)
}
// If both sides are *unknown*, it hardly matters, does it?
@@ -200,14 +200,14 @@ fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
// universe is the minimum of the two universes, because that is
// the one which contains the fewest names in scope.
let universe = cmp::min(universe1, universe2);
Ok(ConstVariableValue::Unknown { universe })
(ConstVariableValue::Unknown { universe }, value1.origin.span)
}
}?;
};
Ok(ConstVarValue {
origin: ConstVariableOrigin {
kind: ConstVariableOriginKind::ConstInference,
span: DUMMY_SP,
span: span,
},
val,
})
+1 -1
View File
@@ -2675,7 +2675,7 @@ pub fn trait_did(&self, tcx: TyCtxt<'tcx>) -> DefId {
}
}
/// Returns `true` if this a type that impls this closure kind
/// Returns `true` if a type that impls this closure kind
/// must also implement `other`.
pub fn extends(self, other: ty::ClosureKind) -> bool {
match (self, other) {
-2
View File
@@ -1,5 +1,3 @@
#![allow(non_camel_case_types)]
use rustc_data_structures::sync::Lock;
use std::fmt::Debug;
@@ -396,7 +396,8 @@ fn highlight_if_we_cannot_match_hir_ty(
) -> Option<RegionNameHighlight> {
let mut highlight = RegionHighlightMode::default();
highlight.highlighting_region_vid(needle_fr, counter);
let type_name = self.infcx.extract_type_name(&ty, Some(highlight)).0;
let type_name =
self.infcx.extract_inference_diagnostics_data(ty.into(), Some(highlight)).name;
debug!(
"highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
@@ -404,7 +405,6 @@ fn highlight_if_we_cannot_match_hir_ty(
);
if type_name.find(&format!("'{}", counter)).is_some() {
// Only add a label if we can confirm that a region was labelled.
Some(RegionNameHighlight::CannotMatchHirTy(span, type_name))
} else {
None
@@ -646,7 +646,8 @@ fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Opti
let mut highlight = RegionHighlightMode::default();
highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
let type_name = self.infcx.extract_type_name(&return_ty, Some(highlight)).0;
let type_name =
self.infcx.extract_inference_diagnostics_data(return_ty.into(), Some(highlight)).name;
let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
@@ -698,7 +699,8 @@ fn give_name_if_anonymous_region_appears_in_yield_ty(
let mut highlight = RegionHighlightMode::default();
highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
let type_name = self.infcx.extract_type_name(&yield_ty, Some(highlight)).0;
let type_name =
self.infcx.extract_inference_diagnostics_data(yield_ty.into(), Some(highlight)).name;
let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
@@ -33,7 +33,6 @@ pub(super) struct Prefixes<'cx, 'tcx> {
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[allow(dead_code)]
pub(super) enum PrefixSet {
/// Doesn't stop until it returns the base case (a Local or
/// Static prefix).
@@ -144,7 +144,6 @@ fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
#[allow(unused)]
struct MovePathLinearIter<'a, 'tcx, F> {
next: Option<(MovePathIndex, &'a MovePath<'tcx>)>,
fetch_next: F,
@@ -112,6 +112,30 @@ fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
}
}
#[derive(Debug)]
pub struct FloatingPointOp;
impl NonConstOp for FloatingPointOp {
const STOPS_CONST_CHECKING: bool = true;
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
if ccx.const_kind() == hir::ConstContext::ConstFn {
Status::Unstable(sym::const_fn_floating_point_arithmetic)
} else {
Status::Allowed
}
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_floating_point_arithmetic,
span,
&format!("floating point arithmetic is not allowed in {}s", ccx.const_kind()),
)
.emit();
}
}
#[derive(Debug)]
pub struct NonPrimitiveOp;
impl NonConstOp for NonPrimitiveOp {
@@ -540,8 +540,12 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
Rvalue::UnaryOp(_, ref operand) => {
let ty = operand.ty(self.body, self.tcx);
if !(ty.is_integral() || ty.is_bool()) {
self.check_op(ops::NonPrimitiveOp)
if is_int_bool_or_char(ty) {
// Int, bool, and char operations are fine.
} else if ty.is_floating_point() {
self.check_op(ops::FloatingPointOp);
} else {
span_bug!(self.span, "non-primitive type in `Rvalue::UnaryOp`: {:?}", ty);
}
}
@@ -550,7 +554,9 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
let lhs_ty = lhs.ty(self.body, self.tcx);
let rhs_ty = rhs.ty(self.body, self.tcx);
if let ty::RawPtr(_) | ty::FnPtr(..) = lhs_ty.kind() {
if is_int_bool_or_char(lhs_ty) && is_int_bool_or_char(rhs_ty) {
// Int, bool, and char operations are fine.
} else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() {
assert_eq!(lhs_ty, rhs_ty);
assert!(
op == BinOp::Eq
@@ -563,12 +569,15 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
);
self.check_op(ops::RawPtrComparison);
}
if !(lhs_ty.is_integral() || lhs_ty.is_bool() || lhs_ty.is_char())
|| !(rhs_ty.is_integral() || rhs_ty.is_bool() || rhs_ty.is_char())
{
self.check_op(ops::NonPrimitiveOp)
} else if lhs_ty.is_floating_point() || rhs_ty.is_floating_point() {
self.check_op(ops::FloatingPointOp);
} else {
span_bug!(
self.span,
"non-primitive type in `Rvalue::BinaryOp`: {:?} ⚬ {:?}",
lhs_ty,
rhs_ty
);
}
}
}
@@ -867,3 +876,7 @@ fn place_as_reborrow(
}
})
}
fn is_int_bool_or_char(ty: Ty<'_>) -> bool {
ty.is_bool() || ty.is_integral() || ty.is_char()
}
-2
View File
@@ -1,5 +1,3 @@
#![allow(non_camel_case_types)]
pub use self::FileMatch::*;
use std::borrow::Cow;
+1
View File
@@ -352,6 +352,7 @@
const_evaluatable_checked,
const_extern_fn,
const_fn,
const_fn_floating_point_arithmetic,
const_fn_transmute,
const_fn_union,
const_generics,
@@ -32,6 +32,7 @@ pub enum AutoTraitResult<A> {
NegativeImpl,
}
#[allow(dead_code)]
impl<A> AutoTraitResult<A> {
fn is_auto(&self) -> bool {
match *self {
@@ -20,7 +20,6 @@
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::fold::TypeFolder;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{
self, fast_reject, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt,
TypeFoldable, WithConstness,
@@ -1513,10 +1512,21 @@ fn maybe_report_ambiguity(
// check upstream for type errors and don't add the obligations to
// begin with in those cases.
if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
self.emit_inference_failure_err(
body_id,
span,
self_ty.into(),
ErrorCode::E0282,
)
.emit();
return;
}
let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
let mut err = self.emit_inference_failure_err(
body_id,
span,
self_ty.into(),
ErrorCode::E0283,
);
err.note(&format!("cannot satisfy `{}`", predicate));
if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
@@ -1580,17 +1590,7 @@ fn maybe_report_ambiguity(
return;
}
match arg.unpack() {
GenericArgKind::Lifetime(lt) => {
span_bug!(span, "unexpected well formed predicate: {:?}", lt)
}
GenericArgKind::Type(ty) => {
self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
}
GenericArgKind::Const(ct) => {
self.need_type_info_err_const(body_id, span, ct, ErrorCode::E0282)
}
}
self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282)
}
ty::PredicateAtom::Subtype(data) => {
@@ -1601,7 +1601,7 @@ fn maybe_report_ambiguity(
let SubtypePredicate { a_is_expected: _, a, b } = data;
// both must be type variables, or the other would've been instantiated
assert!(a.is_ty_var() && b.is_ty_var());
self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282)
}
ty::PredicateAtom::Projection(data) => {
let trait_ref = ty::Binder::bind(data).to_poly_trait_ref(self.tcx);
@@ -1612,7 +1612,12 @@ fn maybe_report_ambiguity(
}
if self_ty.needs_infer() && ty.needs_infer() {
// We do this for the `foo.collect()?` case to produce a suggestion.
let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
let mut err = self.emit_inference_failure_err(
body_id,
span,
self_ty.into(),
ErrorCode::E0284,
);
err.note(&format!("cannot satisfy `{}`", predicate));
err
} else {
@@ -2,7 +2,6 @@
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
#[allow(dead_code)]
pub mod auto_trait;
mod chalk_fulfill;
pub mod codegen;
@@ -2148,7 +2148,6 @@ fn derived_cause(
}
impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> {
#[allow(unused_comparisons)]
fn derived_cause(
&self,
variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
+1 -1
View File
@@ -2991,7 +2991,7 @@ pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
ty
} else {
if !self.is_tainted_by_errors() {
self.need_type_info_err((**self).body_id, sp, ty, E0282)
self.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282)
.note("type must be known at this point")
.emit();
}
+8 -3
View File
@@ -653,7 +653,12 @@ fn new(
fn report_type_error(&self, t: Ty<'tcx>) {
if !self.tcx.sess.has_errors() {
self.infcx
.need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t, E0282)
.emit_inference_failure_err(
Some(self.body.id()),
self.span.to_span(self.tcx),
t.into(),
E0282,
)
.emit();
}
}
@@ -661,10 +666,10 @@ fn report_type_error(&self, t: Ty<'tcx>) {
fn report_const_error(&self, c: &'tcx ty::Const<'tcx>) {
if !self.tcx.sess.has_errors() {
self.infcx
.need_type_info_err_const(
.emit_inference_failure_err(
Some(self.body.id()),
self.span.to_span(self.tcx),
c,
c.into(),
E0282,
)
.emit();
-1
View File
@@ -56,7 +56,6 @@
*/
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![allow(non_camel_case_types)]
#![feature(bool_to_option)]
#![feature(box_syntax)]
#![feature(crate_visibility_modifier)]
+1
View File
@@ -82,6 +82,7 @@
#![feature(const_pin)]
#![feature(const_fn_union)]
#![feature(const_fn)]
#![cfg_attr(not(bootstrap), feature(const_fn_floating_point_arithmetic))]
#![feature(const_generics)]
#![feature(const_option)]
#![feature(const_precise_live_drops)]
+17 -4
View File
@@ -70,10 +70,23 @@
//! }
//! ```
//!
//! This usage of [`Option`] to create safe nullable pointers is so
//! common that Rust does special optimizations to make the
//! representation of [`Option`]`<`[`Box<T>`]`>` a single pointer. Optional pointers
//! in Rust are stored as efficiently as any other pointer type.
//! # Representation
//!
//! Rust guarantees to optimize the following types `T` such that
//! [`Option<T>`] has the same size as `T`:
//!
//! * [`Box<U>`]
//! * `&U`
//! * `&mut U`
//! * `fn`, `extern "C" fn`
//! * [`num::NonZero*`]
//! * [`ptr::NonNull<U>`]
//! * `#[repr(transparent)]` struct around one of the types in this list.
//!
//! It is further guaranteed that, for the cases above, one can
//! [`mem::transmute`] from all valid values of `T` to `Option<T>` and
//! from `Some::<T>(_)` to `T` (but transmuting `None::<T>` to `T`
//! is undefined behaviour).
//!
//! # Examples
//!
+164
View File
@@ -319,6 +319,13 @@ pub(super) trait SplitIter: DoubleEndedIterator {
///
/// This struct is created by the [`split`] method on [slices].
///
/// # Example
///
/// ```
/// let slice = [10, 40, 33, 20];
/// let mut iter = slice.split(|num| num % 3 == 0);
/// ```
///
/// [`split`]: ../../std/primitive.slice.html#method.split
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "rust1", since = "1.0.0")]
@@ -434,6 +441,15 @@ impl<T, P> FusedIterator for Split<'_, T, P> where P: FnMut(&T) -> bool {}
///
/// This struct is created by the [`split_inclusive`] method on [slices].
///
/// # Example
///
/// ```
/// #![feature(split_inclusive)]
///
/// let slice = [10, 40, 33, 20];
/// let mut iter = slice.split_inclusive(|num| num % 3 == 0);
/// ```
///
/// [`split_inclusive`]: ../../std/primitive.slice.html#method.split_inclusive
/// [slices]: ../../std/primitive.slice.html
#[unstable(feature = "split_inclusive", issue = "72360")]
@@ -539,6 +555,13 @@ impl<T, P> FusedIterator for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool
///
/// This struct is created by the [`split_mut`] method on [slices].
///
/// # Example
///
/// ```
/// let mut v = [10, 40, 30, 20, 60, 50];
/// let iter = v.split_mut(|num| *num % 3 == 0);
/// ```
///
/// [`split_mut`]: ../../std/primitive.slice.html#method.split_mut
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "rust1", since = "1.0.0")]
@@ -661,6 +684,15 @@ impl<T, P> FusedIterator for SplitMut<'_, T, P> where P: FnMut(&T) -> bool {}
///
/// This struct is created by the [`split_inclusive_mut`] method on [slices].
///
/// # Example
///
/// ```
/// #![feature(split_inclusive)]
///
/// let mut v = [10, 40, 30, 20, 60, 50];
/// let iter = v.split_inclusive_mut(|num| *num % 3 == 0);
/// ```
///
/// [`split_inclusive_mut`]: ../../std/primitive.slice.html#method.split_inclusive_mut
/// [slices]: ../../std/primitive.slice.html
#[unstable(feature = "split_inclusive", issue = "72360")]
@@ -775,6 +807,13 @@ impl<T, P> FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> b
///
/// This struct is created by the [`rsplit`] method on [slices].
///
/// # Example
///
/// ```
/// let slice = [11, 22, 33, 0, 44, 55];
/// let iter = slice.rsplit(|num| *num == 0);
/// ```
///
/// [`rsplit`]: ../../std/primitive.slice.html#method.rsplit
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "slice_rsplit", since = "1.27.0")]
@@ -854,6 +893,13 @@ impl<T, P> FusedIterator for RSplit<'_, T, P> where P: FnMut(&T) -> bool {}
///
/// This struct is created by the [`rsplit_mut`] method on [slices].
///
/// # Example
///
/// ```
/// let mut slice = [11, 22, 33, 0, 44, 55];
/// let iter = slice.rsplit_mut(|num| *num == 0);
/// ```
///
/// [`rsplit_mut`]: ../../std/primitive.slice.html#method.rsplit_mut
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "slice_rsplit", since = "1.27.0")]
@@ -966,6 +1012,13 @@ fn size_hint(&self) -> (usize, Option<usize>) {
///
/// This struct is created by the [`splitn`] method on [slices].
///
/// # Example
///
/// ```
/// let slice = [10, 40, 30, 20, 60, 50];
/// let iter = slice.splitn(2, |num| *num % 3 == 0);
/// ```
///
/// [`splitn`]: ../../std/primitive.slice.html#method.splitn
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "rust1", since = "1.0.0")]
@@ -999,6 +1052,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
///
/// This struct is created by the [`rsplitn`] method on [slices].
///
/// # Example
///
/// ```
/// let slice = [10, 40, 30, 20, 60, 50];
/// let iter = slice.rsplitn(2, |num| *num % 3 == 0);
/// ```
///
/// [`rsplitn`]: ../../std/primitive.slice.html#method.rsplitn
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1031,6 +1091,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
///
/// This struct is created by the [`splitn_mut`] method on [slices].
///
/// # Example
///
/// ```
/// let mut slice = [10, 40, 30, 20, 60, 50];
/// let iter = slice.splitn_mut(2, |num| *num % 3 == 0);
/// ```
///
/// [`splitn_mut`]: ../../std/primitive.slice.html#method.splitn_mut
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1064,6 +1131,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
///
/// This struct is created by the [`rsplitn_mut`] method on [slices].
///
/// # Example
///
/// ```
/// let mut slice = [10, 40, 30, 20, 60, 50];
/// let iter = slice.rsplitn_mut(2, |num| *num % 3 == 0);
/// ```
///
/// [`rsplitn_mut`]: ../../std/primitive.slice.html#method.rsplitn_mut
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1100,6 +1174,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
///
/// This struct is created by the [`windows`] method on [slices].
///
/// # Example
///
/// ```
/// let slice = ['r', 'u', 's', 't'];
/// let iter = slice.windows(2);
/// ```
///
/// [`windows`]: ../../std/primitive.slice.html#method.windows
/// [slices]: ../../std/primitive.slice.html
#[derive(Debug)]
@@ -1239,6 +1320,13 @@ fn may_have_side_effect() -> bool {
///
/// This struct is created by the [`chunks`] method on [slices].
///
/// # Example
///
/// ```
/// let slice = ['l', 'o', 'r', 'e', 'm'];
/// let iter = slice.chunks(2);
/// ```
///
/// [`chunks`]: ../../std/primitive.slice.html#method.chunks
/// [slices]: ../../std/primitive.slice.html
#[derive(Debug)]
@@ -1400,6 +1488,13 @@ fn may_have_side_effect() -> bool {
///
/// This struct is created by the [`chunks_mut`] method on [slices].
///
/// # Example
///
/// ```
/// let mut slice = ['l', 'o', 'r', 'e', 'm'];
/// let iter = slice.chunks_mut(2);
/// ```
///
/// [`chunks_mut`]: ../../std/primitive.slice.html#method.chunks_mut
/// [slices]: ../../std/primitive.slice.html
#[derive(Debug)]
@@ -1559,6 +1654,13 @@ fn may_have_side_effect() -> bool {
///
/// This struct is created by the [`chunks_exact`] method on [slices].
///
/// # Example
///
/// ```
/// let slice = ['l', 'o', 'r', 'e', 'm'];
/// let iter = slice.chunks_exact(2);
/// ```
///
/// [`chunks_exact`]: ../../std/primitive.slice.html#method.chunks_exact
/// [`remainder`]: ChunksExact::remainder
/// [slices]: ../../std/primitive.slice.html
@@ -1708,6 +1810,13 @@ fn may_have_side_effect() -> bool {
///
/// This struct is created by the [`chunks_exact_mut`] method on [slices].
///
/// # Example
///
/// ```
/// let mut slice = ['l', 'o', 'r', 'e', 'm'];
/// let iter = slice.chunks_exact_mut(2);
/// ```
///
/// [`chunks_exact_mut`]: ../../std/primitive.slice.html#method.chunks_exact_mut
/// [`into_remainder`]: ChunksExactMut::into_remainder
/// [slices]: ../../std/primitive.slice.html
@@ -1850,6 +1959,15 @@ fn may_have_side_effect() -> bool {
///
/// This struct is created by the [`array_windows`] method on [slices].
///
/// # Example
///
/// ```
/// #![feature(array_windows)]
///
/// let slice = [0, 1, 2, 3];
/// let iter = slice.array_windows::<2>();
/// ```
///
/// [`array_windows`]: ../../std/primitive.slice.html#method.array_windows
/// [slices]: ../../std/primitive.slice.html
#[derive(Debug, Clone, Copy)]
@@ -1962,6 +2080,15 @@ fn is_empty(&self) -> bool {
///
/// This struct is created by the [`array_chunks`] method on [slices].
///
/// # Example
///
/// ```
/// #![feature(array_chunks)]
///
/// let slice = ['l', 'o', 'r', 'e', 'm'];
/// let iter = slice.array_chunks::<2>();
/// ```
///
/// [`array_chunks`]: ../../std/primitive.slice.html#method.array_chunks
/// [`remainder`]: ArrayChunks::remainder
/// [slices]: ../../std/primitive.slice.html
@@ -2080,6 +2207,15 @@ fn may_have_side_effect() -> bool {
///
/// This struct is created by the [`array_chunks_mut`] method on [slices].
///
/// # Example
///
/// ```
/// #![feature(array_chunks)]
///
/// let mut slice = ['l', 'o', 'r', 'e', 'm'];
/// let iter = slice.array_chunks_mut::<2>();
/// ```
///
/// [`array_chunks_mut`]: ../../std/primitive.slice.html#method.array_chunks_mut
/// [`into_remainder`]: ../../std/slice/struct.ArrayChunksMut.html#method.into_remainder
/// [slices]: ../../std/primitive.slice.html
@@ -2190,6 +2326,13 @@ fn may_have_side_effect() -> bool {
///
/// This struct is created by the [`rchunks`] method on [slices].
///
/// # Example
///
/// ```
/// let slice = ['l', 'o', 'r', 'e', 'm'];
/// let iter = slice.rchunks(2);
/// ```
///
/// [`rchunks`]: ../../std/primitive.slice.html#method.rchunks
/// [slices]: ../../std/primitive.slice.html
#[derive(Debug)]
@@ -2347,6 +2490,13 @@ fn may_have_side_effect() -> bool {
///
/// This struct is created by the [`rchunks_mut`] method on [slices].
///
/// # Example
///
/// ```
/// let mut slice = ['l', 'o', 'r', 'e', 'm'];
/// let iter = slice.rchunks_mut(2);
/// ```
///
/// [`rchunks_mut`]: ../../std/primitive.slice.html#method.rchunks_mut
/// [slices]: ../../std/primitive.slice.html
#[derive(Debug)]
@@ -2504,6 +2654,13 @@ fn may_have_side_effect() -> bool {
///
/// This struct is created by the [`rchunks_exact`] method on [slices].
///
/// # Example
///
/// ```
/// let slice = ['l', 'o', 'r', 'e', 'm'];
/// let iter = slice.rchunks_exact(2);
/// ```
///
/// [`rchunks_exact`]: ../../std/primitive.slice.html#method.rchunks_exact
/// [`remainder`]: ChunksExact::remainder
/// [slices]: ../../std/primitive.slice.html
@@ -2657,6 +2814,13 @@ fn may_have_side_effect() -> bool {
///
/// This struct is created by the [`rchunks_exact_mut`] method on [slices].
///
/// # Example
///
/// ```
/// let mut slice = ['l', 'o', 'r', 'e', 'm'];
/// let iter = slice.rchunks_exact_mut(2);
/// ```
///
/// [`rchunks_exact_mut`]: ../../std/primitive.slice.html#method.rchunks_exact_mut
/// [`into_remainder`]: ChunksExactMut::into_remainder
/// [slices]: ../../std/primitive.slice.html
+1
View File
@@ -236,6 +236,7 @@
#![feature(clamp)]
#![feature(concat_idents)]
#![feature(const_cstr_unchecked)]
#![cfg_attr(not(bootstrap), feature(const_fn_floating_point_arithmetic))]
#![feature(const_fn_transmute)]
#![feature(const_fn)]
#![feature(const_ip)]
+1
View File
@@ -384,6 +384,7 @@ mod prim_char {}
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_unit {}
#[doc(alias = "ptr")]
#[doc(primitive = "pointer")]
//
/// Raw, unsafe pointers, `*const T`, and `*mut T`.
+1
View File
@@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Non-breaking changes since the last major version]
- Add `x.py setup` [#76631](https://github.com/rust-lang/rust/pull/76631)
- Add a changelog for x.py [#76626](https://github.com/rust-lang/rust/pull/76626)
- Optionally, download LLVM from CI on Linux and NixOS
+ [#76439](https://github.com/rust-lang/rust/pull/76349)
+16 -3
View File
@@ -7,21 +7,34 @@
use std::env;
use bootstrap::{Build, Config};
use bootstrap::{Build, Config, Subcommand};
fn main() {
let args = env::args().skip(1).collect::<Vec<_>>();
let config = Config::parse(&args);
let changelog_suggestion = check_version(&config);
if let Some(suggestion) = &changelog_suggestion {
// NOTE: Since `./configure` generates a `config.toml`, distro maintainers will see the
// changelog warning, not the `x.py setup` message.
let suggest_setup = !config.config.exists() && !matches!(config.cmd, Subcommand::Setup { .. });
if suggest_setup {
println!("warning: you have not made a `config.toml`");
println!("help: consider running `x.py setup` or copying `config.toml.example`");
} else if let Some(suggestion) = &changelog_suggestion {
println!("{}", suggestion);
}
Build::new(config).build();
if let Some(suggestion) = changelog_suggestion {
if suggest_setup {
println!("warning: you have not made a `config.toml`");
println!("help: consider running `x.py setup` or copying `config.toml.example`");
} else if let Some(suggestion) = &changelog_suggestion {
println!("{}", suggestion);
}
if suggest_setup || changelog_suggestion.is_some() {
println!("note: this message was printed twice to make it more likely to be seen");
}
}
+3 -1
View File
@@ -549,7 +549,9 @@ pub fn new(build: &Build) -> Builder<'_> {
Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
Subcommand::Run { ref paths } => (Kind::Run, &paths[..]),
Subcommand::Format { .. } | Subcommand::Clean { .. } => panic!(),
Subcommand::Format { .. } | Subcommand::Clean { .. } | Subcommand::Setup { .. } => {
panic!()
}
};
Self::new_internal(build, kind, paths.to_owned())
+6 -1
View File
@@ -73,6 +73,8 @@ pub struct Config {
pub keep_stage: Vec<u32>,
pub keep_stage_std: Vec<u32>,
pub src: PathBuf,
// defaults to `config.toml`
pub config: PathBuf,
pub jobs: Option<u32>,
pub cmd: Subcommand,
pub incremental: bool,
@@ -513,6 +515,7 @@ pub fn default_opts() -> Config {
config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")];
config.deny_warnings = true;
config.missing_tools = false;
config.config = PathBuf::from("config.toml");
// set by bootstrap.py
config.build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
@@ -558,7 +561,7 @@ pub fn parse(args: &[String]) -> Config {
let get_toml = |file: PathBuf| {
use std::process;
let contents = t!(fs::read_to_string(&file), "configuration file did not exist");
let contents = t!(fs::read_to_string(&file), "`include` config not found");
match toml::from_str(&contents) {
Ok(table) => table,
Err(err) => {
@@ -644,6 +647,7 @@ pub fn parse(args: &[String]) -> Config {
| Subcommand::Clippy { .. }
| Subcommand::Fix { .. }
| Subcommand::Run { .. }
| Subcommand::Setup { .. }
| Subcommand::Format { .. } => flags.stage.unwrap_or(0),
};
@@ -668,6 +672,7 @@ pub fn parse(args: &[String]) -> Config {
| Subcommand::Clippy { .. }
| Subcommand::Fix { .. }
| Subcommand::Run { .. }
| Subcommand::Setup { .. }
| Subcommand::Format { .. } => {}
}
}
+31 -1
View File
@@ -7,6 +7,7 @@
use std::path::PathBuf;
use std::process;
use build_helper::t;
use getopts::Options;
use crate::builder::Builder;
@@ -89,6 +90,9 @@ pub enum Subcommand {
Run {
paths: Vec<PathBuf>,
},
Setup {
path: String,
},
}
impl Default for Subcommand {
@@ -199,6 +203,7 @@ pub fn parse(args: &[String]) -> Flags {
|| (s == "install")
|| (s == "run")
|| (s == "r")
|| (s == "setup")
});
let subcommand = match subcommand {
Some(s) => s,
@@ -453,10 +458,21 @@ pub fn parse(args: &[String]) -> Flags {
At least a tool needs to be called.",
);
}
"setup" => {
subcommand_help.push_str(
"\n
Arguments:
This subcommand accepts a 'profile' to use for builds. For example:
./x.py setup library
The profile is optional and you will be prompted interactively if it is not given.",
);
}
_ => {}
};
// Get any optional paths which occur after the subcommand
let paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
let mut paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);
let verbose = matches.opt_present("verbose");
@@ -508,6 +524,20 @@ pub fn parse(args: &[String]) -> Flags {
}
Subcommand::Run { paths }
}
"setup" => {
let path = if paths.len() > 1 {
println!("\nat most one profile can be passed to setup\n");
usage(1, &opts, verbose, &subcommand_help)
} else if let Some(path) = paths.pop() {
t!(path.into_os_string().into_string().map_err(|path| format!(
"{} is not a valid UTF8 string",
path.to_string_lossy()
)))
} else {
t!(crate::setup::interactive_path())
};
Subcommand::Setup { path }
}
_ => {
usage(1, &opts, verbose, &subcommand_help);
}
+6 -1
View File
@@ -141,6 +141,7 @@
mod native;
mod run;
mod sanity;
mod setup;
mod test;
mod tool;
mod toolstate;
@@ -165,7 +166,7 @@ pub unsafe fn setup(_build: &mut crate::Build) {}
use crate::cache::{Interned, INTERNER};
pub use crate::config::Config;
use crate::flags::Subcommand;
pub use crate::flags::Subcommand;
const LLVM_TOOLS: &[&str] = &[
"llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility
@@ -470,6 +471,10 @@ pub fn build(&mut self) {
return clean::clean(self, all);
}
if let Subcommand::Setup { path: include_name } = &self.config.cmd {
return setup::setup(&self.config.src, include_name);
}
{
let builder = builder::Builder::new(&self);
if let Some(path) = builder.paths.get(0) {
+1 -1
View File
@@ -10,7 +10,7 @@ impl Step for ExpandYamlAnchors {
/// Runs the `expand-yaml_anchors` tool.
///
/// This tool in `src/tools` read the CI configuration files written in YAML and expands the
/// This tool in `src/tools` reads the CI configuration files written in YAML and expands the
/// anchors in them, since GitHub Actions doesn't support them.
fn run(self, builder: &Builder<'_>) {
builder.info("Expanding YAML anchors in the GitHub Actions configuration");
+88
View File
@@ -0,0 +1,88 @@
use crate::t;
use std::path::{Path, PathBuf};
use std::{
env, fs,
io::{self, Write},
};
pub fn setup(src_path: &Path, include_name: &str) {
let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);
if cfg_file.as_ref().map_or(false, |f| f.exists()) {
let file = cfg_file.unwrap();
println!(
"error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
file.display()
);
println!(
"help: try adding `profile = \"{}\"` at the top of {}",
include_name,
file.display()
);
println!(
"note: this will use the configuration in {}/src/bootstrap/defaults/config.toml.{}",
src_path.display(),
include_name
);
std::process::exit(1);
}
let path = cfg_file.unwrap_or_else(|| src_path.join("config.toml"));
let settings = format!(
"# Includes one of the default files in src/bootstrap/defaults\n\
profile = \"{}\"\n",
include_name
);
t!(fs::write(path, settings));
let include_path =
format!("{}/src/bootstrap/defaults/config.toml.{}", src_path.display(), include_name);
println!("`x.py` will now use the configuration at {}", include_path);
let suggestions = match include_name {
"codegen" | "compiler" => &["check", "build", "test"][..],
"library" => &["check", "build", "test library/std", "doc"],
"user" => &["dist", "build"],
_ => return,
};
println!("To get started, try one of the following commands:");
for cmd in suggestions {
println!("- `x.py {}`", cmd);
}
if include_name != "user" {
println!(
"For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
);
}
}
// Used to get the path for `Subcommand::Setup`
pub fn interactive_path() -> io::Result<String> {
let mut input = String::new();
println!(
"Welcome to the Rust project! What do you want to do with x.py?
a) Contribute to the standard library
b) Contribute to the compiler
c) Contribute to the compiler, and also modify LLVM or codegen
d) Install Rust from source"
);
let template = loop {
print!("Please choose one (a/b/c/d): ");
io::stdout().flush()?;
io::stdin().read_line(&mut input)?;
break match input.trim().to_lowercase().as_str() {
"a" | "lib" | "library" => "library",
"b" | "compiler" => "compiler",
"c" | "llvm" => "llvm",
"d" | "user" | "maintainer" => "maintainer",
_ => {
println!("error: unrecognized option '{}'", input.trim());
println!("note: press Ctrl+C to exit");
continue;
}
};
};
Ok(template.to_owned())
}
+19 -19
View File
@@ -256,7 +256,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
// determine if we should display the inner contents or
// the outer `mod` item for the source code.
let whence = {
let span = {
let sm = cx.sess().source_map();
let outer = sm.lookup_char_pos(self.where_outer.lo());
let inner = sm.lookup_char_pos(self.where_inner.lo());
@@ -272,7 +272,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(name),
attrs,
source: whence.clean(cx),
source: span.clean(cx),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
@@ -912,7 +912,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
@@ -1020,7 +1020,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs,
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
@@ -1044,7 +1044,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs,
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
@@ -1830,7 +1830,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
@@ -1850,7 +1850,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
@@ -1880,7 +1880,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
@@ -1899,7 +1899,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
visibility: Inherited,
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
@@ -2047,7 +2047,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
@@ -2062,7 +2062,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
@@ -2093,7 +2093,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
@@ -2114,7 +2114,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: def_id.to_def_id(),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
@@ -2168,7 +2168,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| Item {
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: def_id.to_def_id(),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
@@ -2219,7 +2219,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
vec![Item {
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
visibility: self.vis.clean(cx),
stability: None,
@@ -2284,7 +2284,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
vec![Item {
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: DefId::local(CRATE_DEF_INDEX),
visibility: self.vis.clean(cx),
stability: None,
@@ -2326,7 +2326,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
@@ -2342,7 +2342,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(name.clone()),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
visibility: Public,
stability: cx.stability(self.hid).clean(cx),
deprecation: cx.deprecation(self.hid).clean(cx),
@@ -2367,7 +2367,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
source: self.span.clean(cx),
visibility: Public,
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
+17 -17
View File
@@ -89,7 +89,7 @@ pub struct Struct<'hir> {
pub generics: &'hir hir::Generics<'hir>,
pub attrs: &'hir [ast::Attribute],
pub fields: &'hir [hir::StructField<'hir>],
pub whence: Span,
pub span: Span,
}
pub struct Union<'hir> {
@@ -100,7 +100,7 @@ pub struct Union<'hir> {
pub generics: &'hir hir::Generics<'hir>,
pub attrs: &'hir [ast::Attribute],
pub fields: &'hir [hir::StructField<'hir>],
pub whence: Span,
pub span: Span,
}
pub struct Enum<'hir> {
@@ -109,7 +109,7 @@ pub struct Enum<'hir> {
pub generics: &'hir hir::Generics<'hir>,
pub attrs: &'hir [ast::Attribute],
pub id: hir::HirId,
pub whence: Span,
pub span: Span,
pub name: Symbol,
}
@@ -118,7 +118,7 @@ pub struct Variant<'hir> {
pub id: hir::HirId,
pub attrs: &'hir [ast::Attribute],
pub def: &'hir hir::VariantData<'hir>,
pub whence: Span,
pub span: Span,
}
pub struct Function<'hir> {
@@ -128,7 +128,7 @@ pub struct Function<'hir> {
pub name: Symbol,
pub vis: &'hir hir::Visibility<'hir>,
pub header: hir::FnHeader,
pub whence: Span,
pub span: Span,
pub generics: &'hir hir::Generics<'hir>,
pub body: hir::BodyId,
}
@@ -139,7 +139,7 @@ pub struct Typedef<'hir> {
pub name: Symbol,
pub id: hir::HirId,
pub attrs: &'hir [ast::Attribute],
pub whence: Span,
pub span: Span,
pub vis: &'hir hir::Visibility<'hir>,
}
@@ -148,7 +148,7 @@ pub struct OpaqueTy<'hir> {
pub name: Symbol,
pub id: hir::HirId,
pub attrs: &'hir [ast::Attribute],
pub whence: Span,
pub span: Span,
pub vis: &'hir hir::Visibility<'hir>,
}
@@ -161,7 +161,7 @@ pub struct Static<'hir> {
pub attrs: &'hir [ast::Attribute],
pub vis: &'hir hir::Visibility<'hir>,
pub id: hir::HirId,
pub whence: Span,
pub span: Span,
}
pub struct Constant<'hir> {
@@ -171,7 +171,7 @@ pub struct Constant<'hir> {
pub attrs: &'hir [ast::Attribute],
pub vis: &'hir hir::Visibility<'hir>,
pub id: hir::HirId,
pub whence: Span,
pub span: Span,
}
pub struct Trait<'hir> {
@@ -183,7 +183,7 @@ pub struct Trait<'hir> {
pub bounds: &'hir [hir::GenericBound<'hir>],
pub attrs: &'hir [ast::Attribute],
pub id: hir::HirId,
pub whence: Span,
pub span: Span,
pub vis: &'hir hir::Visibility<'hir>,
}
@@ -193,7 +193,7 @@ pub struct TraitAlias<'hir> {
pub bounds: &'hir [hir::GenericBound<'hir>],
pub attrs: &'hir [ast::Attribute],
pub id: hir::HirId,
pub whence: Span,
pub span: Span,
pub vis: &'hir hir::Visibility<'hir>,
}
@@ -208,7 +208,7 @@ pub struct Impl<'hir> {
pub for_: &'hir hir::Ty<'hir>,
pub items: Vec<&'hir hir::ImplItem<'hir>>,
pub attrs: &'hir [ast::Attribute],
pub whence: Span,
pub span: Span,
pub vis: &'hir hir::Visibility<'hir>,
pub id: hir::HirId,
}
@@ -219,7 +219,7 @@ pub struct ForeignItem<'hir> {
pub name: Symbol,
pub kind: &'hir hir::ForeignItemKind<'hir>,
pub attrs: &'hir [ast::Attribute],
pub whence: Span,
pub span: Span,
}
// For Macro we store the DefId instead of the NodeId, since we also create
@@ -229,7 +229,7 @@ pub struct Macro<'hir> {
pub hid: hir::HirId,
pub def_id: hir::def_id::DefId,
pub attrs: &'hir [ast::Attribute],
pub whence: Span,
pub span: Span,
pub matchers: Vec<Span>,
pub imported_from: Option<Symbol>,
}
@@ -240,7 +240,7 @@ pub struct ExternCrate<'hir> {
pub path: Option<String>,
pub vis: &'hir hir::Visibility<'hir>,
pub attrs: &'hir [ast::Attribute],
pub whence: Span,
pub span: Span,
}
pub struct Import<'hir> {
@@ -250,7 +250,7 @@ pub struct Import<'hir> {
pub attrs: &'hir [ast::Attribute],
pub path: &'hir hir::Path<'hir>,
pub glob: bool,
pub whence: Span,
pub span: Span,
}
pub struct ProcMacro<'hir> {
@@ -259,7 +259,7 @@ pub struct ProcMacro<'hir> {
pub kind: MacroKind,
pub helpers: Vec<Symbol>,
pub attrs: &'hir [ast::Attribute],
pub whence: Span,
pub span: Span,
}
pub fn struct_type_from_def(vdata: &hir::VariantData<'_>) -> StructType {
+17 -17
View File
@@ -99,7 +99,7 @@ fn visit_variant_data(
attrs: &item.attrs,
generics,
fields: sd.fields(),
whence: item.span,
span: item.span,
}
}
@@ -120,7 +120,7 @@ fn visit_union_data(
attrs: &item.attrs,
generics,
fields: sd.fields(),
whence: item.span,
span: item.span,
}
}
@@ -142,14 +142,14 @@ fn visit_enum_def(
id: v.id,
attrs: &v.attrs,
def: &v.data,
whence: v.span,
span: v.span,
})
.collect(),
vis: &it.vis,
generics,
attrs: &it.attrs,
id: it.hir_id,
whence: it.span,
span: it.span,
}
}
@@ -208,7 +208,7 @@ fn visit_fn(
kind,
helpers,
attrs: &item.attrs,
whence: item.span,
span: item.span,
});
}
None => {
@@ -218,7 +218,7 @@ fn visit_fn(
attrs: &item.attrs,
decl,
name,
whence: item.span,
span: item.span,
generics,
header,
body,
@@ -402,7 +402,7 @@ fn visit_item(
path: orig_name.map(|x| x.to_string()),
vis: &item.vis,
attrs: &item.attrs,
whence: item.span,
span: item.span,
})
}
hir::ItemKind::Use(_, hir::UseKind::ListStem) => {}
@@ -444,7 +444,7 @@ fn visit_item(
attrs: &item.attrs,
path,
glob: is_glob,
whence: item.span,
span: item.span,
});
}
hir::ItemKind::Mod(ref m) => {
@@ -476,7 +476,7 @@ fn visit_item(
name: ident.name,
id: item.hir_id,
attrs: &item.attrs,
whence: item.span,
span: item.span,
vis: &item.vis,
};
om.typedefs.push(t);
@@ -487,7 +487,7 @@ fn visit_item(
name: ident.name,
id: item.hir_id,
attrs: &item.attrs,
whence: item.span,
span: item.span,
vis: &item.vis,
};
om.opaque_tys.push(t);
@@ -500,7 +500,7 @@ fn visit_item(
id: item.hir_id,
name: ident.name,
attrs: &item.attrs,
whence: item.span,
span: item.span,
vis: &item.vis,
};
om.statics.push(s);
@@ -515,7 +515,7 @@ fn visit_item(
id: item.hir_id,
name: ident.name,
attrs: &item.attrs,
whence: item.span,
span: item.span,
vis: &item.vis,
};
om.constants.push(s);
@@ -532,7 +532,7 @@ fn visit_item(
bounds,
id: item.hir_id,
attrs: &item.attrs,
whence: item.span,
span: item.span,
vis: &item.vis,
};
om.traits.push(t);
@@ -544,7 +544,7 @@ fn visit_item(
bounds,
id: item.hir_id,
attrs: &item.attrs,
whence: item.span,
span: item.span,
vis: &item.vis,
};
om.trait_aliases.push(t);
@@ -577,7 +577,7 @@ fn visit_item(
items,
attrs: &item.attrs,
id: item.hir_id,
whence: item.span,
span: item.span,
vis: &item.vis,
};
om.impls.push(i);
@@ -603,7 +603,7 @@ fn visit_foreign_item(
kind: &item.kind,
vis: &item.vis,
attrs: &item.attrs,
whence: item.span,
span: item.span,
});
}
@@ -623,7 +623,7 @@ fn visit_local_macro(
def_id: self.cx.tcx.hir().local_def_id(def.hir_id).to_def_id(),
attrs: &def.attrs,
name: renamed.unwrap_or(def.ident.name),
whence: def.span,
span: def.span,
matchers,
imported_from: None,
}
@@ -2,9 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/cannot-infer-const-args.rs:12:5
|
LL | foo();
| ^^^
|
= note: cannot infer the value of the const parameter `X`
| ^^^ cannot infer the value of const parameter `X` declared on the function `foo`
error: aborting due to previous error
@@ -2,9 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/cannot-infer-const-args.rs:12:5
|
LL | foo();
| ^^^
|
= note: cannot infer the value of the const parameter `X`
| ^^^ cannot infer the value of const parameter `X` declared on the function `foo`
error: aborting due to previous error
@@ -0,0 +1,16 @@
#![feature(min_const_generics)]
use std::convert::TryInto;
fn take_array_from_mut<T, const N: usize>(data: &mut [T], start: usize) -> &mut [T; N] {
(&mut data[start .. start + N]).try_into().unwrap()
}
fn main() {
let mut arr = [0, 1, 2, 3, 4, 5, 6, 7, 8];
for i in 1 .. 4 {
println!("{:?}", take_array_from_mut(&mut arr, i));
//~^ ERROR type annotations needed
}
}
@@ -0,0 +1,9 @@
error[E0282]: type annotations needed
--> $DIR/issue-77092.rs:13:26
|
LL | println!("{:?}", take_array_from_mut(&mut arr, i));
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `{_: usize}`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.
@@ -2,9 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/method-chain.rs:21:33
|
LL | Foo.bar().bar().bar().bar().baz();
| ^^^
|
= note: cannot infer the value of the const parameter `N`
| ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz`
error: aborting due to previous error
@@ -2,9 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/method-chain.rs:21:33
|
LL | Foo.bar().bar().bar().bar().baz();
| ^^^
|
= note: cannot infer the value of the const parameter `N`
| ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz`
error: aborting due to previous error
@@ -2,9 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/uninferred-consts.rs:14:9
|
LL | Foo.foo();
| ^^^
|
= note: cannot infer the value of the const parameter `N`
| ^^^ cannot infer the value of const parameter `N` declared on the associated function `foo`
error: aborting due to previous error
@@ -2,9 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/uninferred-consts.rs:14:9
|
LL | Foo.foo();
| ^^^
|
= note: cannot infer the value of the const parameter `N`
| ^^^ cannot infer the value of const parameter `N` declared on the associated function `foo`
error: aborting due to previous error
@@ -4,7 +4,7 @@
const unsafe extern "C" fn closure() -> fn() { || {} }
//~^ ERROR function pointers in const fn are unstable
const unsafe extern fn use_float() { 1.0 + 1.0; }
//~^ ERROR only int, `bool` and `char` operations are stable in const fn
//~^ ERROR floating point arithmetic
const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
//~^ ERROR casting pointers to integers
@@ -7,14 +7,14 @@ LL | const unsafe extern "C" fn closure() -> fn() { || {} }
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: only int, `bool` and `char` operations are stable in const fn
error[E0658]: floating point arithmetic is not allowed in constant functions
--> $DIR/const-extern-fn-min-const-fn.rs:6:38
|
LL | const unsafe extern fn use_float() { 1.0 + 1.0; }
| ^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= note: see issue #57241 <https://github.com/rust-lang/rust/issues/57241> for more information
= help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable
error[E0658]: casting pointers to integers in constant functions is unstable
--> $DIR/const-extern-fn-min-const-fn.rs:8:48
@@ -0,0 +1,8 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/const_fn_floating_point_arithmetic.rs:20:1
|
LL | fn main() {}
| ^^^^^^^^^
error: aborting due to previous error
@@ -0,0 +1,20 @@
// gate-test-const_fn_floating_point_arithmetic
// revisions: stock gated
#![feature(rustc_attrs)]
#![cfg_attr(gated, feature(const_fn_floating_point_arithmetic))]
const fn add(f: f32) -> f32 { f + 2.0 }
//[stock]~^ floating point arithmetic
const fn sub(f: f32) -> f32 { 2.0 - f }
//[stock]~^ floating point arithmetic
const fn mul(f: f32, g: f32) -> f32 { f * g }
//[stock]~^ floating point arithmetic
const fn div(f: f32, g: f32) -> f32 { f / g }
//[stock]~^ floating point arithmetic
const fn neg(f: f32) -> f32 { -f }
//[stock]~^ floating point arithmetic
#[rustc_error]
fn main() {} //[gated]~ fatal error triggered by #[rustc_error]
@@ -0,0 +1,48 @@
error[E0658]: floating point arithmetic is not allowed in constant functions
--> $DIR/const_fn_floating_point_arithmetic.rs:8:31
|
LL | const fn add(f: f32) -> f32 { f + 2.0 }
| ^^^^^^^
|
= note: see issue #57241 <https://github.com/rust-lang/rust/issues/57241> for more information
= help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable
error[E0658]: floating point arithmetic is not allowed in constant functions
--> $DIR/const_fn_floating_point_arithmetic.rs:10:31
|
LL | const fn sub(f: f32) -> f32 { 2.0 - f }
| ^^^^^^^
|
= note: see issue #57241 <https://github.com/rust-lang/rust/issues/57241> for more information
= help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable
error[E0658]: floating point arithmetic is not allowed in constant functions
--> $DIR/const_fn_floating_point_arithmetic.rs:12:39
|
LL | const fn mul(f: f32, g: f32) -> f32 { f * g }
| ^^^^^
|
= note: see issue #57241 <https://github.com/rust-lang/rust/issues/57241> for more information
= help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable
error[E0658]: floating point arithmetic is not allowed in constant functions
--> $DIR/const_fn_floating_point_arithmetic.rs:14:39
|
LL | const fn div(f: f32, g: f32) -> f32 { f / g }
| ^^^^^
|
= note: see issue #57241 <https://github.com/rust-lang/rust/issues/57241> for more information
= help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable
error[E0658]: floating point arithmetic is not allowed in constant functions
--> $DIR/const_fn_floating_point_arithmetic.rs:16:31
|
LL | const fn neg(f: f32) -> f32 { -f }
| ^^
|
= note: see issue #57241 <https://github.com/rust-lang/rust/issues/57241> for more information
= help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0658`.
+2 -2
View File
@@ -1,6 +1,6 @@
// build-pass (FIXME(62277): could be check-pass?)
// run-pass
#![feature(const_fn)]
#![feature(const_fn_floating_point_arithmetic)]
struct Foo<T>(T);
struct Bar<T> { x: T }
@@ -77,14 +77,6 @@ const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
const fn foo11_2<T: Send>(t: T) -> T { t }
//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
const fn foo19(f: f32) -> f32 { f * 2.0 }
//~^ ERROR int, `bool` and `char` operations
const fn foo19_2(f: f32) -> f32 { 2.0 - f }
//~^ ERROR int, `bool` and `char` operations
const fn foo19_3(f: f32) -> f32 { -f }
//~^ ERROR int, `bool` and `char` operations
const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
//~^ ERROR int, `bool` and `char` operations
static BAR: u32 = 42;
const fn foo25() -> u32 { BAR } //~ ERROR cannot refer to statics
@@ -76,44 +76,8 @@ LL | const fn foo11_2<T: Send>(t: T) -> T { t }
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: only int, `bool` and `char` operations are stable in const fn
--> $DIR/min_const_fn.rs:80:33
|
LL | const fn foo19(f: f32) -> f32 { f * 2.0 }
| ^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: only int, `bool` and `char` operations are stable in const fn
--> $DIR/min_const_fn.rs:82:35
|
LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
| ^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: only int, `bool` and `char` operations are stable in const fn
--> $DIR/min_const_fn.rs:84:35
|
LL | const fn foo19_3(f: f32) -> f32 { -f }
| ^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: only int, `bool` and `char` operations are stable in const fn
--> $DIR/min_const_fn.rs:86:43
|
LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
| ^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0013]: constant functions cannot refer to statics
--> $DIR/min_const_fn.rs:90:27
--> $DIR/min_const_fn.rs:82:27
|
LL | const fn foo25() -> u32 { BAR }
| ^^^
@@ -121,7 +85,7 @@ LL | const fn foo25() -> u32 { BAR }
= help: consider extracting the value of the `static` to a `const`, and referring to that
error[E0013]: constant functions cannot refer to statics
--> $DIR/min_const_fn.rs:91:37
--> $DIR/min_const_fn.rs:83:37
|
LL | const fn foo26() -> &'static u32 { &BAR }
| ^^^
@@ -129,7 +93,7 @@ LL | const fn foo26() -> &'static u32 { &BAR }
= help: consider extracting the value of the `static` to a `const`, and referring to that
error[E0658]: casting pointers to integers in constant functions is unstable
--> $DIR/min_const_fn.rs:92:42
--> $DIR/min_const_fn.rs:84:42
|
LL | const fn foo30(x: *const u32) -> usize { x as usize }
| ^^^^^^^^^^
@@ -138,7 +102,7 @@ LL | const fn foo30(x: *const u32) -> usize { x as usize }
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
error[E0658]: casting pointers to integers in constant functions is unstable
--> $DIR/min_const_fn.rs:94:63
--> $DIR/min_const_fn.rs:86:63
|
LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
| ^^^^^^^^^^
@@ -147,7 +111,7 @@ LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize }
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
error[E0658]: casting pointers to integers in constant functions is unstable
--> $DIR/min_const_fn.rs:96:42
--> $DIR/min_const_fn.rs:88:42
|
LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
| ^^^^^^^^^^
@@ -156,7 +120,7 @@ LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
error[E0658]: casting pointers to integers in constant functions is unstable
--> $DIR/min_const_fn.rs:98:63
--> $DIR/min_const_fn.rs:90:63
|
LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
| ^^^^^^^^^^
@@ -165,7 +129,7 @@ LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize }
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
error[E0658]: mutable references are not allowed in constant functions
--> $DIR/min_const_fn.rs:101:14
--> $DIR/min_const_fn.rs:93:14
|
LL | const fn inc(x: &mut i32) { *x += 1 }
| ^
@@ -174,7 +138,7 @@ LL | const fn inc(x: &mut i32) { *x += 1 }
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:110:6
--> $DIR/min_const_fn.rs:102:6
|
LL | impl<T: std::fmt::Debug> Foo<T> {
| ^
@@ -183,7 +147,7 @@ LL | impl<T: std::fmt::Debug> Foo<T> {
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:115:6
--> $DIR/min_const_fn.rs:107:6
|
LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
| ^
@@ -192,7 +156,7 @@ LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:120:6
--> $DIR/min_const_fn.rs:112:6
|
LL | impl<T: Sync + Sized> Foo<T> {
| ^
@@ -201,7 +165,7 @@ LL | impl<T: Sync + Sized> Foo<T> {
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:126:34
--> $DIR/min_const_fn.rs:118:34
|
LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
| ^^^^^^^^^^^^^^^^^^^^
@@ -210,7 +174,7 @@ LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:128:22
--> $DIR/min_const_fn.rs:120:22
|
LL | const fn no_apit(_x: impl std::fmt::Debug) {}
| ^^^^^^^^^^^^^^^^^^^^
@@ -219,7 +183,7 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {}
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:129:23
--> $DIR/min_const_fn.rs:121:23
|
LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
| ^^
@@ -228,7 +192,7 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:130:32
--> $DIR/min_const_fn.rs:122:32
|
LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -237,7 +201,7 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:135:41
--> $DIR/min_const_fn.rs:127:41
|
LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -246,7 +210,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: function pointers in const fn are unstable
--> $DIR/min_const_fn.rs:138:21
--> $DIR/min_const_fn.rs:130:21
|
LL | const fn no_fn_ptrs(_x: fn()) {}
| ^^
@@ -255,7 +219,7 @@ LL | const fn no_fn_ptrs(_x: fn()) {}
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: function pointers in const fn are unstable
--> $DIR/min_const_fn.rs:140:27
--> $DIR/min_const_fn.rs:132:27
|
LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
| ^^^^
@@ -263,7 +227,7 @@ LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error: aborting due to 30 previous errors
error: aborting due to 26 previous errors
Some errors have detailed explanations: E0013, E0493, E0658, E0723.
For more information about an error, try `rustc --explain E0013`.
@@ -3,7 +3,7 @@
we're apparently really bad at it",
issue = "none")]
#![feature(const_fn, foo, foo2)]
#![feature(const_fn, const_fn_floating_point_arithmetic, foo, foo2)]
#![feature(staged_api)]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -25,9 +25,9 @@ const fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// conformity is required, even with `const_fn` feature gate
// Const-stable functions cannot rely on unstable const-eval features.
const fn bar3() -> u32 { (5f32 + 6f32) as u32 }
//~^ ERROR const-stable function cannot use `#[feature(const_fn)]`
//~^ ERROR const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]`
// check whether this function cannot be called even with the feature gate active
#[unstable(feature = "foo2", issue = "none")]
@@ -14,7 +14,7 @@ LL | const fn bar2() -> u32 { foo2() }
|
= help: Const-stable functions can only call other const-stable functions
error: const-stable function cannot use `#[feature(const_fn)]`
error: const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]`
--> $DIR/min_const_fn_libstd_stability.rs:29:26
|
LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 }
@@ -3,7 +3,7 @@
we're apparently really bad at it",
issue = "none")]
#![feature(const_fn, foo, foo2)]
#![feature(const_fn, const_fn_floating_point_arithmetic, foo, foo2)]
#![feature(staged_api)]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -27,7 +27,7 @@
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// conformity is required, even with `const_fn` feature gate
const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 }
//~^ ERROR const-stable function cannot use `#[feature(const_fn)]`
//~^ ERROR const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]`
// check whether this function cannot be called even with the feature gate active
#[unstable(feature = "foo2", issue = "none")]
@@ -14,7 +14,7 @@ LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
|
= help: Const-stable functions can only call other const-stable functions
error: const-stable function cannot use `#[feature(const_fn)]`
error: const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]`
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:29:33
|
LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 }
+1 -1
View File
@@ -9,6 +9,6 @@ edition = "2018"
clap = "2.25.0"
[dependencies.mdbook]
version = "0.4.0"
version = "0.4.3"
default-features = false
features = ["search"]