Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Rollup of 15 pull requests #77191

Closed
wants to merge 36 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4bfdcea
Add regression test
JulianKnodt Sep 2, 2020
26d6081
Relax promises about condition variable.
m-ou-se Sep 19, 2020
3e08354
Correct file path after some restructures in compiler
tesuji Sep 20, 2020
4387480
Add unstably const support for assume intrinsic
tesuji Sep 20, 2020
4b6a482
Fix dest prop miscompilation around references
jonas-schievink Sep 22, 2020
928a29f
Bless mir-opt tests
jonas-schievink Sep 22, 2020
438d229
dead_code: look at trait impls even if they don't contain items
lcnr Sep 22, 2020
9f27f37
Include libunwind in the rust-src component.
ehuss Sep 23, 2020
631c688
Make [].as_[mut_]ptr_range() (unstably) const.
m-ou-se Sep 23, 2020
b5d47bf
clarify that `changelog-seen = 1` goes to the beginning of config.toml
matthiaskrgr Sep 23, 2020
df004df
Re-download LLVM on submodule updates only
Mark-Simulacrum Sep 23, 2020
ef95430
Adjust support expectations for downloaded LLVMs
Mark-Simulacrum Sep 23, 2020
4de836e
Install std for non-host targets
Mark-Simulacrum Sep 24, 2020
382d724
move test to intergrated test in library/core
tesuji Sep 24, 2020
1857184
remove enum name from ImplSource variants
lcnr Sep 24, 2020
1d3717d
Removing erroneous semicolon
austinkeeley Sep 25, 2020
1e64d98
BTreeMap: refactor correct_childrens_parent_links
ssomers Aug 9, 2020
3965524
BTreeMap: introduce edge methods similar to those of keys and values
ssomers Aug 9, 2020
55fa8af
BTreeMap: various tweaks
ssomers Aug 9, 2020
54c9c94
Allow multiple allow_internal_unstable attributes
bugadani Sep 25, 2020
606ed2a
Remove extra space from vec drawing
pickfire Sep 25, 2020
b4ba7aa
Rollup merge of #76257 - JulianKnodt:i75777, r=Dylan-DPC
jonas-schievink Sep 25, 2020
8880ff4
Rollup merge of #76932 - fusion-engineering-forks:condvar-promise, r=…
jonas-schievink Sep 25, 2020
b7585c5
Rollup merge of #76973 - lzutao:unstably-const-assume, r=oli-obk
jonas-schievink Sep 25, 2020
1652288
Rollup merge of #77005 - ssomers:btree_cleanup_3, r=Mark-Simulacrum
jonas-schievink Sep 25, 2020
a010758
Rollup merge of #77066 - jonas-schievink:dest-prop-borrow, r=oli-obk
jonas-schievink Sep 25, 2020
cc4ec0b
Rollup merge of #77073 - lcnr:ty-trait-param, r=matthewjasper
jonas-schievink Sep 25, 2020
272d4ab
Rollup merge of #77086 - ehuss:src-libunwind, r=Mark-Simulacrum
jonas-schievink Sep 25, 2020
6af9d3c
Rollup merge of #77097 - fusion-engineering-forks:slice-ptr-range-con…
jonas-schievink Sep 25, 2020
3744e1c
Rollup merge of #77106 - matthiaskrgr:changelog_seen, r=Mark-Simulacrum
jonas-schievink Sep 25, 2020
6fca5cc
Rollup merge of #77126 - Mark-Simulacrum:llvm-less-often, r=alexcrichton
jonas-schievink Sep 25, 2020
2e7840e
Rollup merge of #77146 - Mark-Simulacrum:xpyinstall, r=alexcrichton
jonas-schievink Sep 25, 2020
a3be921
Rollup merge of #77155 - lcnr:ImplSource, r=ecstatic-morse
jonas-schievink Sep 25, 2020
3506bdf
Rollup merge of #77176 - austinkeeley:intrinsics-documentatation-erro…
jonas-schievink Sep 25, 2020
49bc727
Rollup merge of #77183 - bugadani:issue-77088, r=varkor
jonas-schievink Sep 25, 2020
4e2c52f
Rollup merge of #77189 - pickfire:patch-5, r=Mark-Simulacrum
jonas-schievink Sep 25, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1022,14 +1022,21 @@ pub fn find_transparency(

pub fn allow_internal_unstable<'a>(
sess: &'a Session,
attrs: &[Attribute],
attrs: &'a [Attribute],
) -> Option<impl Iterator<Item = Symbol> + 'a> {
let attr = sess.find_by_name(attrs, sym::allow_internal_unstable)?;
let list = attr.meta_item_list().or_else(|| {
sess.diagnostic()
.span_err(attr.span, "allow_internal_unstable expects list of feature names");
None
})?;
let attrs = sess.filter_by_name(attrs, sym::allow_internal_unstable);
let list = attrs
.filter_map(move |attr| {
attr.meta_item_list().or_else(|| {
sess.diagnostic().span_err(
attr.span,
"`allow_internal_unstable` expects a list of feature names",
);
None
})
})
.flatten();

Some(list.into_iter().filter_map(move |it| {
let name = it.ident().map(|ident| ident.name);
if name.is_none() {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use rustc_span::Span;
use rustc_target::abi::call::FnAbi;

pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
/// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
/// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
/// add them to librustc_codegen_llvm/context.rs
/// Remember to add all intrinsics here, in `compiler/rustc_typeck/src/check/mod.rs`,
/// and in `library/core/src/intrinsics.rs`; if you need access to any LLVM intrinsics,
/// add them to `compiler/rustc_codegen_llvm/src/context.rs`.
fn codegen_intrinsic_call(
&mut self,
instance: ty::Instance<'tcx>,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_error_codes/src/error_codes/E0092.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ extern "rust-intrinsic" {
```

Please check you didn't make a mistake in the function's name. All intrinsic
functions are defined in `librustc_codegen_llvm/intrinsic.rs` and in
`libcore/intrinsics.rs` in the Rust source code. Example:
functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in
`library/core/src/intrinsics.rs` in the Rust source code. Example:

```
#![feature(intrinsics)]
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_error_codes/src/error_codes/E0093.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ fn main() {
```

Please check you didn't make a mistake in the function's name. All intrinsic
functions are defined in `librustc_codegen_llvm/intrinsic.rs` and in
`libcore/intrinsics.rs` in the Rust source code. Example:
functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in
`library/core/src/intrinsics.rs` in the Rust source code. Example:

```
#![feature(intrinsics)]
Expand Down
89 changes: 44 additions & 45 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, Selecti

pub type CanonicalChalkEnvironmentAndGoal<'tcx> = Canonical<'tcx, ChalkEnvironmentAndGoal<'tcx>>;

pub use self::ImplSource::*;
pub use self::ObligationCauseCode::*;

pub use self::chalk::{ChalkEnvironmentAndGoal, RustInterner as ChalkRustInterner};
Expand Down Expand Up @@ -418,10 +417,10 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
///
/// // Case B: ImplSource must be provided by caller. This applies when
/// // type is a type parameter.
/// param.clone(); // ImplSourceParam
/// param.clone(); // ImplSource::Param
///
/// // Case C: A mix of cases A and B.
/// mixed.clone(); // ImplSource(Impl_1, [ImplSourceParam])
/// mixed.clone(); // ImplSource(Impl_1, [ImplSource::Param])
/// }
/// ```
///
Expand All @@ -431,72 +430,72 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub enum ImplSource<'tcx, N> {
/// ImplSource identifying a particular impl.
ImplSourceUserDefined(ImplSourceUserDefinedData<'tcx, N>),
UserDefined(ImplSourceUserDefinedData<'tcx, N>),

/// ImplSource for auto trait implementations.
/// This carries the information and nested obligations with regards
/// to an auto implementation for a trait `Trait`. The nested obligations
/// ensure the trait implementation holds for all the constituent types.
ImplSourceAutoImpl(ImplSourceAutoImplData<N>),
AutoImpl(ImplSourceAutoImplData<N>),

/// Successful resolution to an obligation provided by the caller
/// for some type parameter. The `Vec<N>` represents the
/// obligations incurred from normalizing the where-clause (if
/// any).
ImplSourceParam(Vec<N>),
Param(Vec<N>),

/// Virtual calls through an object.
ImplSourceObject(ImplSourceObjectData<'tcx, N>),
Object(ImplSourceObjectData<'tcx, N>),

/// Successful resolution for a builtin trait.
ImplSourceBuiltin(ImplSourceBuiltinData<N>),
Builtin(ImplSourceBuiltinData<N>),

/// ImplSource automatically generated for a closure. The `DefId` is the ID
/// of the closure expression. This is a `ImplSourceUserDefined` in spirit, but the
/// of the closure expression. This is a `ImplSource::UserDefined` in spirit, but the
/// impl is generated by the compiler and does not appear in the source.
ImplSourceClosure(ImplSourceClosureData<'tcx, N>),
Closure(ImplSourceClosureData<'tcx, N>),

/// Same as above, but for a function pointer type with the given signature.
ImplSourceFnPointer(ImplSourceFnPointerData<'tcx, N>),
FnPointer(ImplSourceFnPointerData<'tcx, N>),

/// ImplSource for a builtin `DeterminantKind` trait implementation.
ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData),
DiscriminantKind(ImplSourceDiscriminantKindData),

/// ImplSource automatically generated for a generator.
ImplSourceGenerator(ImplSourceGeneratorData<'tcx, N>),
Generator(ImplSourceGeneratorData<'tcx, N>),

/// ImplSource for a trait alias.
ImplSourceTraitAlias(ImplSourceTraitAliasData<'tcx, N>),
TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
}

impl<'tcx, N> ImplSource<'tcx, N> {
pub fn nested_obligations(self) -> Vec<N> {
match self {
ImplSourceUserDefined(i) => i.nested,
ImplSourceParam(n) => n,
ImplSourceBuiltin(i) => i.nested,
ImplSourceAutoImpl(d) => d.nested,
ImplSourceClosure(c) => c.nested,
ImplSourceGenerator(c) => c.nested,
ImplSourceObject(d) => d.nested,
ImplSourceFnPointer(d) => d.nested,
ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData) => Vec::new(),
ImplSourceTraitAlias(d) => d.nested,
ImplSource::UserDefined(i) => i.nested,
ImplSource::Param(n) => n,
ImplSource::Builtin(i) => i.nested,
ImplSource::AutoImpl(d) => d.nested,
ImplSource::Closure(c) => c.nested,
ImplSource::Generator(c) => c.nested,
ImplSource::Object(d) => d.nested,
ImplSource::FnPointer(d) => d.nested,
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) => Vec::new(),
ImplSource::TraitAlias(d) => d.nested,
}
}

pub fn borrow_nested_obligations(&self) -> &[N] {
match &self {
ImplSourceUserDefined(i) => &i.nested[..],
ImplSourceParam(n) => &n[..],
ImplSourceBuiltin(i) => &i.nested[..],
ImplSourceAutoImpl(d) => &d.nested[..],
ImplSourceClosure(c) => &c.nested[..],
ImplSourceGenerator(c) => &c.nested[..],
ImplSourceObject(d) => &d.nested[..],
ImplSourceFnPointer(d) => &d.nested[..],
ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData) => &[],
ImplSourceTraitAlias(d) => &d.nested[..],
ImplSource::UserDefined(i) => &i.nested[..],
ImplSource::Param(n) => &n[..],
ImplSource::Builtin(i) => &i.nested[..],
ImplSource::AutoImpl(d) => &d.nested[..],
ImplSource::Closure(c) => &c.nested[..],
ImplSource::Generator(c) => &c.nested[..],
ImplSource::Object(d) => &d.nested[..],
ImplSource::FnPointer(d) => &d.nested[..],
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) => &[],
ImplSource::TraitAlias(d) => &d.nested[..],
}
}

Expand All @@ -505,42 +504,42 @@ impl<'tcx, N> ImplSource<'tcx, N> {
F: FnMut(N) -> M,
{
match self {
ImplSourceUserDefined(i) => ImplSourceUserDefined(ImplSourceUserDefinedData {
ImplSource::UserDefined(i) => ImplSource::UserDefined(ImplSourceUserDefinedData {
impl_def_id: i.impl_def_id,
substs: i.substs,
nested: i.nested.into_iter().map(f).collect(),
}),
ImplSourceParam(n) => ImplSourceParam(n.into_iter().map(f).collect()),
ImplSourceBuiltin(i) => ImplSourceBuiltin(ImplSourceBuiltinData {
ImplSource::Param(n) => ImplSource::Param(n.into_iter().map(f).collect()),
ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData {
nested: i.nested.into_iter().map(f).collect(),
}),
ImplSourceObject(o) => ImplSourceObject(ImplSourceObjectData {
ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData {
upcast_trait_ref: o.upcast_trait_ref,
vtable_base: o.vtable_base,
nested: o.nested.into_iter().map(f).collect(),
}),
ImplSourceAutoImpl(d) => ImplSourceAutoImpl(ImplSourceAutoImplData {
ImplSource::AutoImpl(d) => ImplSource::AutoImpl(ImplSourceAutoImplData {
trait_def_id: d.trait_def_id,
nested: d.nested.into_iter().map(f).collect(),
}),
ImplSourceClosure(c) => ImplSourceClosure(ImplSourceClosureData {
ImplSource::Closure(c) => ImplSource::Closure(ImplSourceClosureData {
closure_def_id: c.closure_def_id,
substs: c.substs,
nested: c.nested.into_iter().map(f).collect(),
}),
ImplSourceGenerator(c) => ImplSourceGenerator(ImplSourceGeneratorData {
ImplSource::Generator(c) => ImplSource::Generator(ImplSourceGeneratorData {
generator_def_id: c.generator_def_id,
substs: c.substs,
nested: c.nested.into_iter().map(f).collect(),
}),
ImplSourceFnPointer(p) => ImplSourceFnPointer(ImplSourceFnPointerData {
ImplSource::FnPointer(p) => ImplSource::FnPointer(ImplSourceFnPointerData {
fn_ty: p.fn_ty,
nested: p.nested.into_iter().map(f).collect(),
}),
ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData) => {
ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData)
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) => {
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
}
ImplSourceTraitAlias(d) => ImplSourceTraitAlias(ImplSourceTraitAliasData {
ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData {
alias_def_id: d.alias_def_id,
substs: d.substs,
nested: d.nested.into_iter().map(f).collect(),
Expand Down
22 changes: 11 additions & 11 deletions compiler/rustc_middle/src/traits/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,25 @@ use std::fmt;
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
super::ImplSourceUserDefined(ref v) => write!(f, "{:?}", v),
super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v),

super::ImplSourceAutoImpl(ref t) => write!(f, "{:?}", t),
super::ImplSource::AutoImpl(ref t) => write!(f, "{:?}", t),

super::ImplSourceClosure(ref d) => write!(f, "{:?}", d),
super::ImplSource::Closure(ref d) => write!(f, "{:?}", d),

super::ImplSourceGenerator(ref d) => write!(f, "{:?}", d),
super::ImplSource::Generator(ref d) => write!(f, "{:?}", d),

super::ImplSourceFnPointer(ref d) => write!(f, "ImplSourceFnPointer({:?})", d),
super::ImplSource::FnPointer(ref d) => write!(f, "({:?})", d),

super::ImplSourceDiscriminantKind(ref d) => write!(f, "{:?}", d),
super::ImplSource::DiscriminantKind(ref d) => write!(f, "{:?}", d),

super::ImplSourceObject(ref d) => write!(f, "{:?}", d),
super::ImplSource::Object(ref d) => write!(f, "{:?}", d),

super::ImplSourceParam(ref n) => write!(f, "ImplSourceParam({:?})", n),
super::ImplSource::Param(ref n) => write!(f, "ImplSourceParamData({:?})", n),

super::ImplSourceBuiltin(ref d) => write!(f, "{:?}", d),
super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d),

super::ImplSourceTraitAlias(ref d) => write!(f, "{:?}", d),
super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d),
}
}
}
Expand Down Expand Up @@ -96,7 +96,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx,
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"ImplSourceTraitAlias(alias_def_id={:?}, substs={:?}, nested={:?})",
"ImplSourceTraitAliasData(alias_def_id={:?}, substs={:?}, nested={:?})",
self.alias_def_id, self.substs, self.nested
)
}
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_mir/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// These just return their argument
self.copy_op(args[0], dest)?;
}
sym::assume => {
let cond = self.read_scalar(args[0])?.check_init()?.to_bool()?;
if !cond {
throw_ub_format!("`assume` intrinsic called with `false`");
}
}
_ => return Ok(false),
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir/src/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ty::InstanceDef::Virtual(_, idx) => {
let mut args = args.to_vec();
// We have to implement all "object safe receivers". Currently we
// support built-in pointers (&, &mut, Box) as well as unsized-self. We do
// support built-in pointers `(&, &mut, Box)` as well as unsized-self. We do
// not yet support custom self types.
// Also see librustc_codegen_llvm/abi.rs and librustc_codegen_llvm/mir/block.rs.
// Also see `compiler/rustc_codegen_llvm/src/abi.rs` and `compiler/rustc_codegen_ssa/src/mir/block.rs`.
let receiver_place = match args[0].layout.ty.builtin_deref(true) {
Some(_) => {
// Built-in pointer.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir/src/monomorphize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fn custom_coerce_unsize_info<'tcx>(
});

match tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref)) {
Ok(traits::ImplSourceUserDefined(traits::ImplSourceUserDefinedData {
Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
impl_def_id,
..
})) => tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir/src/transform/dest_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> {
// FIXME: This can be smarter and take `StorageDead` into account (which
// invalidates borrows).
if self.ever_borrowed_locals.contains(dest.local)
&& self.ever_borrowed_locals.contains(src.local)
|| self.ever_borrowed_locals.contains(src.local)
{
return;
}
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_passes/src/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ fn has_allow_dead_code_or_lang_attr(
// - This is because lang items are always callable from elsewhere.
// or
// 2) We are not sure to be live or not
// * Implementation of a trait method
// * Implementations of traits and trait methods
struct LifeSeeder<'k, 'tcx> {
worklist: Vec<hir::HirId>,
krate: &'k hir::Crate<'k>,
Expand Down Expand Up @@ -415,6 +415,9 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
}
}
hir::ItemKind::Impl { ref of_trait, items, .. } => {
if of_trait.is_some() {
self.worklist.push(item.hir_id);
}
for impl_item_ref in items {
let impl_item = self.krate.impl_item(impl_item_ref.id);
if of_trait.is_some()
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_trait_selection/src/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
));

match result {
Ok(Some(ImplSource::ImplSourceUserDefined(_))) => {
Ok(Some(ImplSource::UserDefined(_))) => {
debug!(
"find_auto_trait_generics({:?}): \
manual impl found, bailing out",
Expand Down Expand Up @@ -315,9 +315,8 @@ impl AutoTraitFinder<'tcx> {
// If we see an explicit negative impl (e.g., `impl !Send for MyStruct`),
// we immediately bail out, since it's impossible for us to continue.

if let ImplSource::ImplSourceUserDefined(ImplSourceUserDefinedData {
impl_def_id,
..
if let ImplSource::UserDefined(ImplSourceUserDefinedData {
impl_def_id, ..
}) = impl_source
{
// Blame 'tidy' for the weird bracket placement.
Expand Down
Loading